diff options
Diffstat (limited to 'klaptopdaemon')
101 files changed, 17540 insertions, 0 deletions
diff --git a/klaptopdaemon/Makefile.am b/klaptopdaemon/Makefile.am new file mode 100644 index 0000000..8a2e737 --- /dev/null +++ b/klaptopdaemon/Makefile.am @@ -0,0 +1,49 @@ +kde_module_LTLIBRARIES = kcm_laptop.la kded_klaptopdaemon.la +bin_PROGRAMS = klaptop_acpi_helper klaptop_check +lib_LTLIBRARIES = libkcmlaptop.la +SUBDIRS = pics applnk + +libkcmlaptop_la_SOURCES = portable.cpp smapidev.c daemon_state.cpp wake_laptop.cpp krichtextlabel.cpp +libkcmlaptop_la_LDFLAGS = $(all_libraries) +libkcmlaptop_la_LIBADD = $(LIB_KDEUI) + +MESSAGE_SOURCES = laptop_daemon.cpp kpcmcia.cpp xautolock.cc kpcmciainfo.cpp daemondock.cpp xautolock_diy.c xautolock_engine.c +kded_klaptopdaemon_la_SOURCES = $(MESSAGE_SOURCES) laptop_daemon.skel +kded_klaptopdaemon_la_LDFLAGS = $(all_libraries) -module -avoid-version -lXtst +kded_klaptopdaemon_la_LIBADD = $(LIB_KDEUI) $(LIB_XSS) libkcmlaptop.la + +klaptop_acpi_helper_SOURCES = acpi_helper.cpp + +klaptop_check_SOURCES = laptop_check.cpp +klaptop_check_LDFLAGS = $(all_libraries) +klaptop_check_LDADD = $(LIB_KFILE) $(LIB_KDEUI) libkcmlaptop.la + +kcm_laptop_la_SOURCES = battery.cpp main.cpp pcmcia.cpp power.cpp warning.cpp \ + acpi.cpp sony.cpp profile.cpp buttons.cpp apm.cpp +kcm_laptop_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kcm_laptop_la_LIBADD = $(LIB_KFILE) $(LIB_KDEUI) libkcmlaptop.la +kcm_laptop_la_COMPILE_FIRST = crcresult.h + +AM_CPPFLAGS = $(all_includes) + +AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +KDE_OPTIONS = nofinal + +kcm_laptop_la_METASOURCES = AUTO + +messages: + $(XGETTEXT) $(libkcmlaptop_la_SOURCES) $(klaptop_acpi_helper_SOURCES) $(klaptop_check_SOURCES) $(MESSAGE_SOURCES) -o $(podir)/klaptopdaemon.pot + $(XGETTEXT) $(kcm_laptop_la_SOURCES) -o $(podir)/kcmlaptop.pot + +dummy.cpp: + echo >dummy.cpp + +noinst_PROGRAMS = makecrc +makecrc_SOURCES = makecrc.cpp +makecrc_LDADD = $(LIBZ) + +crcresult.h: makecrc klaptop_acpi_helper + ./makecrc >crcresult.h + +CLEANFILES = crcresult.h makecrc diff --git a/klaptopdaemon/README b/klaptopdaemon/README new file mode 100644 index 0000000..858e0ff --- /dev/null +++ b/klaptopdaemon/README @@ -0,0 +1,8 @@ +This is klaptop daemon it provides battery monitoring and management +for laptops - this is a KDE 2 rewrite of kcmlaptop which is not +supported for KDE >2.0. Please pass any bug reports to Paul Campbell + +The power management stuff is all abstracted out into portable.* +if you feel the urge to port it to your OS/CPU please contact me for +help - Paul diff --git a/klaptopdaemon/acpi.cpp b/klaptopdaemon/acpi.cpp new file mode 100644 index 0000000..cb13f40 --- /dev/null +++ b/klaptopdaemon/acpi.cpp @@ -0,0 +1,281 @@ +/* + * acpi.cpp + * + * Copyright (c) 1999, 2003 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "acpi.h" +#include "version.h" +#include "portable.h" +#include <stdlib.h> +#include <unistd.h> + +// other KDE headers: +#include <klocale.h> +#include <kconfig.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kprocess.h> + +// other Qt headers: +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qhgroupbox.h> +#include <qgrid.h> +#include <qpushbutton.h> +#include <qtooltip.h> +extern void wake_laptop_daemon(); + +AcpiConfig::AcpiConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *tmp_label = new QLabel( i18n("This panel provides information about your system's ACPI implementation " + "and lets you have access to some of the extra features provided by ACPI"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("NOTE: the Linux ACPI implementation is still a 'work in progress'. " + "Some features, in particular suspend and hibernate are not yet available " + "under 2.4 - and under 2.5 some particular ACPI implementations are still " + "unstable, these check boxes let you only enable the things that work reliably. " + "You should test these features very gingerly - save all your work, check them " + "on and try a suspend/standby/hibernate from the popup menu on the battery icon " + "in the panel if it fails to come back successfully uncheck the box again."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("Some changes made on this page may require you to quit the laptop panel " + "and start it again to take effect"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + bool can_enable = laptop_portable::has_acpi(1); // is helper ready + enableStandby = new QCheckBox( i18n("Enable standby"), this ); + top_layout->addWidget( enableStandby ); + QToolTip::add( enableStandby, i18n( "If checked this box enables transitions to the 'standby' state - a temporary powered down state" ) ); + enableStandby->setEnabled(can_enable); + connect( enableStandby, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableSuspend = new QCheckBox( i18n("Enable &suspend"), this ); + top_layout->addWidget( enableSuspend ); + QToolTip::add( enableSuspend, i18n( "If checked this box enables transitions to the 'suspend' state - a semi-powered down state, sometimes called 'suspend-to-ram'" ) ); + enableSuspend->setEnabled(can_enable); + connect( enableSuspend, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + QHBoxLayout *ll = new QHBoxLayout(); + enableHibernate = new QCheckBox( i18n("Enable &hibernate"), this ); + ll->addWidget( enableHibernate ); + QToolTip::add( enableHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state - a powered down state, sometimes called 'suspend-to-disk'" ) ); + enableHibernate->setEnabled(can_enable); + connect( enableHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + if (laptop_portable::has_software_suspend()) { + ll->addStretch(1); + enableSoftwareSuspendHibernate = new QCheckBox( i18n("Use software suspend for hibernate"), this ); + ll->addWidget( enableSoftwareSuspendHibernate ); + QToolTip::add( enableSoftwareSuspendHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state - a powered down state, sometimes called 'suspend-to-disk' - the kernel 'Software Suspend' mechanism will be used instead of using ACPI directly" ) ); + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + connect( enableSoftwareSuspendHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + } else { + enableSoftwareSuspendHibernate = 0; + } + ll->addStretch(10); + + top_layout->addLayout(ll); + + enablePerformance = new QCheckBox( i18n("Enable &performance profiles"), this ); + top_layout->addWidget( enablePerformance ); + QToolTip::add( enablePerformance, i18n( "If checked this box enables access to ACPI performance profiles - usually OK in 2.4 and later" ) ); + enablePerformance->setEnabled(can_enable); + connect( enablePerformance, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableThrottle = new QCheckBox( i18n("Enable &CPU throttling"), this ); + top_layout->addWidget( enableThrottle ); + QToolTip::add( enableThrottle, i18n( "If checked this box enables access to ACPI throttle speed changes - usually OK in 2.4 and later" ) ); + enableThrottle->setEnabled(can_enable); + connect( enableThrottle, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + tmp_label = new QLabel(i18n("If the above boxes are disabled then there is no 'helper' " + "application set up to help change ACPI states, there are two " + "ways you can enable this application, either make the file " + "/proc/acpi/sleep writeable by anyone every time your system boots " + "or use the button below to make the KDE ACPI helper application " + "set-uid root"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + ll = new QHBoxLayout(); + QPushButton *setupButton = new QPushButton(i18n("Setup Helper Application"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the ACPI helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + top_layout->addLayout(ll); + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +AcpiConfig::~AcpiConfig() +{ + delete config; +} + +#include "checkcrc.h" +#include "crcresult.h" +#include <qfile.h> + +void AcpiConfig::setupHelper() +{ + unsigned long len, crc; + QString helper = KStandardDirs::findExe("klaptop_acpi_helper"); + checkcrc(QFile::encodeName(helper), len, crc); + if (len != file_len || crc != file_crc) { + QString str(i18n("The %1 application does not seem to have " + "the same size or checksum as when it was compiled we do NOT recommend " + "you proceed with making it setuid-root without further investigation").arg(helper)); + int rc = KMessageBox::warningContinueCancel(0, str, i18n("KLaptopDaemon"), i18n("Run Nevertheless")); + if (rc != KMessageBox::Continue) + return; + } + + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the klaptop_acpi_helper to change."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chown root "+helper+"; chmod +s "+helper; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The ACPI helper cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + bool can_enable = laptop_portable::has_acpi(1); // is helper ready + enableStandby->setEnabled(can_enable); + enableSuspend->setEnabled(can_enable); + enableHibernate->setEnabled(can_enable); + enablePerformance->setEnabled(can_enable); + enableThrottle->setEnabled(can_enable); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + wake_laptop_daemon(); +} + + +void AcpiConfig::save() +{ + enablestandby = enableStandby->isChecked(); + enablesuspend = enableSuspend->isChecked(); + enablehibernate = enableHibernate->isChecked(); + enablesoftwaresuspend = (enableSoftwareSuspendHibernate?enableSoftwareSuspendHibernate->isChecked():0); + enableperformance = enablePerformance->isChecked(); + enablethrottle = enableThrottle->isChecked(); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config->setGroup("AcpiDefault"); + + config->writeEntry("EnableStandby", enablestandby); + config->writeEntry("EnableSuspend", enablesuspend); + config->writeEntry("EnableHibernate", enablehibernate); + config->writeEntry("EnableThrottle", enablethrottle); + config->writeEntry("EnablePerformance", enableperformance); + config->setGroup("SoftwareSuspendDefault"); + config->writeEntry("EnableHibernate", enablesoftwaresuspend); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void AcpiConfig::load() +{ + load( false ); +} + +void AcpiConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("AcpiDefault"); + + enablestandby = config->readBoolEntry("EnableStandby", false); + enableStandby->setChecked(enablestandby); + enablesuspend = config->readBoolEntry("EnableSuspend", false); + enableSuspend->setChecked(enablesuspend); + enablehibernate = config->readBoolEntry("EnableHibernate", false); + enableHibernate->setChecked(enablehibernate); + enableperformance = config->readBoolEntry("EnablePerformance", false); + enablePerformance->setChecked(enableperformance); + enablethrottle = config->readBoolEntry("EnableThrottle", false); + enableThrottle->setChecked(enablethrottle); + config->setGroup("SoftwareSuspendDefault"); + enablesoftwaresuspend = config->readBoolEntry("EnableHibernate", false); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setChecked(enablesoftwaresuspend); + + emit changed(useDefaults); +} + +void AcpiConfig::defaults() +{ + load( true ); +} + + +void AcpiConfig::configChanged() +{ + emit changed(true); +} + + +QString AcpiConfig::quickHelp() const +{ + return i18n("<h1>ACPI Setup</h1>This module allows you to configure ACPI for your system"); +} + +#include "acpi.moc" + + diff --git a/klaptopdaemon/acpi.h b/klaptopdaemon/acpi.h new file mode 100644 index 0000000..a6a77cb --- /dev/null +++ b/klaptopdaemon/acpi.h @@ -0,0 +1,72 @@ +/* + * acpi.h + * + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __ACPICONFIG_H__ +#define __ACPICONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class AcpiConfig : public KCModule +{ + Q_OBJECT +public: + AcpiConfig( QWidget *parent=0, const char* name=0); + ~AcpiConfig( ); + + void save( void ); + void load(); + void load( bool useDefaults ); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void setupHelper(); + +private: + KConfig *config; + + QCheckBox *enableHibernate; + QCheckBox *enableSuspend; + QCheckBox *enableStandby; + QCheckBox *enablePerformance; + QCheckBox *enableThrottle; + QCheckBox *enableSoftwareSuspendHibernate; + bool enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle, enablesoftwaresuspend; +}; + +#endif + diff --git a/klaptopdaemon/acpi_helper.cpp b/klaptopdaemon/acpi_helper.cpp new file mode 100644 index 0000000..660d2cb --- /dev/null +++ b/klaptopdaemon/acpi_helper.cpp @@ -0,0 +1,325 @@ +/* + * acpi_helper.cpp - acpi helper + * + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// README!! +// +// This file contains code that is intended to be run setuid root +// (only if the end user enables it themselves, it's not set that +// way as part of a standard KDE build). +// +// Because of this this code should be simple and easily visually +// inspected for security holes and/or bugs - if you feel the need +// to change this file please get someone else to review your work +// (I'll happily do it for you - mail me at [email protected], please +// review mine!) +// +// I recommend the following practices here - both for safety and +// transparency: +// +// - check all array references (snprintf/strncpy etc) +// +// - avoid malloc/new calls and pointers too if possible +// + +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> +#include <string.h> + +#define MAX_TOSHIBA_STRING 64 + +/* Write a value to /proc/acpi/sleep, where value may be between + 1 and 4 (whatever they mean). Does not return; calls exit(). */ + +void write_to_proc_sleep(int value) +{ + char tmp[256]; + int fd; + + /* Sanity check value */ + if ((value<1) || (value>4)) + exit(1); + + /* Convert value to string */ + snprintf(tmp,sizeof(tmp),"%d",value); + tmp[sizeof(tmp)-1]=0; + + /* Broken imitation of typing sync <enter> sync <enter> + on the command line before shutting down the machine; + part of the lore of UNIX machines. */ + sync(); + sync(); + fd = open("/proc/acpi/sleep", O_RDWR); + if (fd < 0) + exit(1); + write(fd, tmp, 1); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); +} + +/* Write string to new acpi power interface */ +void write_to_power(const char * str) +{ + int fd; + /* Broken imitation of typing sync <enter> sync <enter> + on the command line before shutting down the machine; + part of the lore of UNIX machines. */ + sync(); + sync(); + fd = open("/sys/power/state", O_RDWR); + if (fd < 0) + exit(1); + write(fd, str, strlen(str)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); +} + +/* Run the program @param path, if it exists and seems safe to do so. + Returns only if the program does not exist; if the program exists + and is unsafe, exit; if the program exists and is safe, run it + and never return. */ +void run_program(const char *path) +{ + struct stat sb; + int err; + + if (!path) exit(1); /* Bad pointer */ + if (path[0] != '/') exit(1); /* Not an absolute path */ + + if ((err = stat(path, &sb)) != 0 || sb.st_mode&S_IWOTH) { + if (err != 0) { + fprintf(stderr, "Can't find %s\n", path); + return; + } else { + fprintf(stderr, "%s is writeable by anyone - we don't trust it\n", path); + } + exit(1); + } + ::setuid(::geteuid()); // otherwise bash will throw it away + ::execl(path, NULL); // this is not KDE environment code + exit(0); +} + +int +main(int argc, char **argv) +{ + int fd; + int i; + int toshibalcd_val = 0; + bool useSysPower=false; + + fd = open("/sys/power/state", O_RDWR); + if (fd >= 0) + useSysPower=true; + close(fd); + + ::close(0); // we're setuid - this is just in case + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "--suspend") == 0 || strcmp(argv[i], "-suspend") == 0) { + /* Returns only if suspend does not exist. */ + run_program("/usr/sbin/suspend"); + if (useSysPower) + write_to_power("mem"); + else + write_to_proc_sleep(3); + exit(0); + } else + if (strcmp(argv[i], "--standby") == 0 || strcmp(argv[i], "-standby") == 0) { + if (useSysPower) + write_to_power("standby"); + else + write_to_proc_sleep(1); + exit(0); + } else + if (strcmp(argv[i], "--standby2") == 0 || strcmp(argv[i], "-standby2") == 0) { + write_to_proc_sleep(2); + exit(0); + } else + if (strcmp(argv[i], "--hibernate") == 0 || strcmp(argv[i], "-hibernate") == 0) { + run_program("/usr/sbin/hibernate"); + if (useSysPower) + write_to_power("disk"); + else + write_to_proc_sleep(4); + exit(0); + } else + if (strcmp(argv[i], "--software-suspend") == 0 || strcmp(argv[i], "-software-suspend") == 0) { + run_program("/usr/sbin/hibernate"); + exit(0); + } else + if (strcmp(argv[i], "--throttling") == 0 || strcmp(argv[i], "-throttling") == 0) { + int val; + char tmp[256]; + + i++; + if (i >= argc) + break; + if (strlen(argv[i]) > 50 || strchr(argv[i], '.')) + break; + snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/throttling", argv[i]); + tmp[sizeof(tmp)-1] = 0; + i++; + if (i >= argc) + break; + val= atoi(argv[i]); + if (val < 0) + break; + sync(); + sync(); + fd = open(tmp, O_RDWR); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else + if (strcmp(argv[i], "--performance") == 0 || strcmp(argv[i], "-performance") == 0) { + int val; + char tmp[256]; + + i++; + if (i >= argc) + break; + if (strlen(argv[i]) > 50 || strchr(argv[i], '.')) + break; + snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/performance", argv[i]); + tmp[sizeof(tmp)-1] = 0; + i++; + if (i >= argc) + break; + val= atoi(argv[i]); + if (val < 0) + break; + sync(); + sync(); + fd = open(tmp, O_RDWR); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else + if (strcmp(argv[i], "--toshibalcd") == 0 || strcmp(argv[i], "-toshibalcd") == 0) { + + i++; + if (i >= argc) + break; + toshibalcd_val= atoi(argv[i]); + if (toshibalcd_val < 0) + toshibalcd_val = 0; + if (toshibalcd_val > 7) + toshibalcd_val = 7; + fd = open("/proc/acpi/TOSHIBA1/lcd", O_RDWR); + if (fd >= 0 ) { + char c; + + c = '0'+toshibalcd_val; + write(fd, &c, 1); + close(fd); + } else { + fd = open("/proc/acpi/toshiba/lcd", O_RDWR); + if (fd >= 0) { + char str[MAX_TOSHIBA_STRING]; + + snprintf(str,sizeof(str),"brightness : %d",toshibalcd_val); + str[sizeof(str)-1]=0; + write(fd,str,strlen(str)); + close(fd); + } + } + setuid(getuid()); // drop all priority asap + exit(0); + } else + // CPUFreq support + if (strncmp(argv[i], "--cpufreq", 9) == 0 || strncmp(argv[i], "-cpufreq", 8) == 0) { + if ((i+1) >= argc) + break; + if (strlen(argv[i+1]) > 50 || strchr(argv[i+1], '.')) + break; + int val; + char tmp[256]; + // CPUFreq support for the interface of the 2.4 kernell (/proc/sys/cpu/N/) + if (strcmp(argv[i], "--cpufreq-24") == 0 || strcmp(argv[i], "-cpufreq-24") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "/proc/sys/cpu/%s/speed", argv[i]); + tmp[sizeof(tmp)-1] = 0; + ++i; + if (i >= argc) + break; + val = atoi(argv[i]); + if (val < 0) + break; + fd = open(tmp, O_WRONLY); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + } else + // CPUFreq support for the interface of the 2.5 kernel (/proc/cpufreq) + if (strcmp(argv[i], "--cpufreq-25") == 0 || strcmp(argv[i], "-cpufreq-25") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "%s", argv[i]); + tmp[sizeof(tmp)-1] = 0; + fd = open("/proc/cpufreq", O_WRONLY); + if (fd < 0) + exit(1); + write(fd, tmp, strlen(tmp)); + } else + // CPUFreq support fot the sysfs interface of the 2.5 kernel (/sys/devices/sys/cpuN/cpufreq/) + if (strcmp(argv[i], "--cpufreq-sysfs") == 0 || strcmp(argv[i], "-cpufreq-sysfs") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", argv[i]); + tmp[sizeof(tmp)-1] = 0; + ++i; + if (i >= argc) + break; + fd = open(tmp, O_WRONLY); + if (fd < 0) + exit(1); + if (strlen(argv[i]) > 50) + break; + snprintf(tmp, sizeof(tmp), "%s", argv[i]); + tmp[sizeof(tmp)-1] = 0; + write(fd, tmp, strlen(tmp)); + } else { + break; + } + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else { +usage: + setuid(getuid()); // drop all priority asap + fprintf(stderr, "Usage: %s [--suspend] [--standby] [--hibernate][--software-suspend][--toshibalcd N][--performance CPU N][--throttling CPU N][--cpufreq-[24|25|sysfs]]\n", argv[0]); + exit(1); + } + goto usage; + +} + diff --git a/klaptopdaemon/apm.cpp b/klaptopdaemon/apm.cpp new file mode 100644 index 0000000..a13a907 --- /dev/null +++ b/klaptopdaemon/apm.cpp @@ -0,0 +1,285 @@ +/* + * battery.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "apm.h" +#include "version.h" +#include "portable.h" +#include <stdlib.h> +#include <unistd.h> + +// other KDE headers: +#include <klocale.h> +#include <kconfig.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kprocess.h> + +// other Qt headers: +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qgrid.h> +#include <qpushbutton.h> +#include <qtooltip.h> +extern void wake_laptop_daemon(); + +ApmConfig::ApmConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *tmp_label = new QLabel( i18n("This panel lets you configure your APM system and lets " + "you have access to some of the extra features provided by it"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("NOTE: some APM implementations have buggy suspend/standby " + "implementations. You should test these features very gingerly - save " + "all your work, check them on and try a suspend/standby from " + "the popup menu on the battery icon in the panel if it fails to come " + "back successfully uncheck the box again."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("Some changes made on this page may require you to quit the laptop panel " + "and start it again to take effect"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + bool can_enable = laptop_portable::has_apm(1); // is helper ready + enableStandby = new QCheckBox( i18n("Enable standby"), this ); + top_layout->addWidget( enableStandby ); + QToolTip::add( enableStandby, i18n( "If checked this box enables transitions to the 'standby' state - a temporary powered down state" ) ); + enableStandby->setEnabled(can_enable); + connect( enableStandby, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableSuspend = new QCheckBox( i18n("Enable &suspend"), this ); + top_layout->addWidget( enableSuspend ); + QToolTip::add( enableSuspend, i18n( "If checked this box enables transitions to the 'suspend' state - a semi-powered down state, sometimes called 'suspend-to-ram'" ) ); + enableSuspend->setEnabled(can_enable); + connect( enableSuspend, SIGNAL(clicked()), this, SLOT(configChanged()) ); + apm_name = "/usr/bin/apm"; + if (::access(apm_name, F_OK) != 0 && ::access("/usr/sbin/apm", F_OK) == 0) + apm_name = "/usr/sbin/apm"; + + tmp_label = new QLabel(i18n("If the above boxes are disabled then there is no 'helper' " + "application set up to help change APM states, there are two " + "ways you can enable this application, either make the file " + "/proc/apm writeable by anyone every time your system boots " + "or use the button below to make the %1 application " + "set-uid root").arg(apm_name), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + QHBoxLayout *ll = new QHBoxLayout(top_layout); + QPushButton *setupButton = new QPushButton(i18n("Setup Helper Application"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the APM helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + if (laptop_portable::has_software_suspend()) { + tmp_label = new QLabel( i18n("Your system seems to have 'Software Suspend' installed, this can " + "be used to hibernate or 'suspend to disk' your system if you want " + "to use this for hibernation check the box below"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + enableSoftwareSuspendHibernate = new QCheckBox( i18n("Enable software suspend for hibernate"), this ); + top_layout->addWidget( enableSoftwareSuspendHibernate ); + QToolTip::add( enableSoftwareSuspendHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state using the 'Software Suspend' mechanism" ) ); + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + connect( enableSoftwareSuspendHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + tmp_label = new QLabel( i18n("If the above box is disabled then you need to be logged in " + "as root or need a helper application to invoke the Software " + "Suspend utility - KDE provides a utility to do this, if you " + "wish to use it you must make it set-uid root, the button " + "below will do this for you"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + ll = new QHBoxLayout(this); + QPushButton *setupSSButton = new QPushButton(i18n("Setup SS Helper Application"), this); + connect( setupSSButton, SIGNAL(clicked()), this, SLOT(setupHelper2()) ); + QToolTip::add( setupSSButton, i18n( "This button can be used to enable the Software Suspend helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupSSButton); + ll->addStretch(8); + } else { + enableSoftwareSuspendHibernate = 0; + } + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +ApmConfig::~ApmConfig() +{ + delete config; +} + +void ApmConfig::setupHelper() +{ + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the %1 application to change.").arg(apm_name), + "KLaptopDaemon", KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << QString("chown root ")+apm_name+"; chmod +s "+apm_name; + proc.start(KProcess::Block); // run it sync so has_apm below sees the results + } + } else { + KMessageBox::sorry(0, i18n("%1 cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly.").arg(QString(apm_name)), + i18n("KLaptopDaemon")); + } + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + bool can_enable = laptop_portable::has_apm(1); // is helper ready + enableStandby->setEnabled(can_enable); + enableSuspend->setEnabled(can_enable); + wake_laptop_daemon(); +} + +#include "checkcrc.h" +#include "crcresult.h" +void ApmConfig::setupHelper2() // we use the acpi helper to do software suspend +{ + unsigned long len, crc; + QString helper = KStandardDirs::findExe("klaptop_acpi_helper"); + checkcrc(helper.latin1(), len, crc); + if (len != file_len || crc != file_crc) { + QString str(i18n("The %1 application does not seem to have " + "the same size or checksum as when it was compiled we do NOT recommend " + "you proceed with making it setuid-root without further investigation").arg(helper)); + int rc = KMessageBox::warningContinueCancel(0, str, i18n("KLaptopDaemon"), i18n("Run Nevertheless")); + if (rc != KMessageBox::Continue) + return; + } + + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the klaptop_acpi_helper to change."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chown root "+helper+"; chmod +s "+helper; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The Software Suspend helper cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + laptop_portable::software_suspend_set_mask(enablesoftwaresuspend); + bool can_enable = laptop_portable::has_software_suspend(2); // is helper ready + enableSoftwareSuspendHibernate->setEnabled(can_enable); + wake_laptop_daemon(); +} + + +void ApmConfig::save() +{ + enablestandby = enableStandby->isChecked(); + enablesuspend = enableSuspend->isChecked(); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + enablesoftwaresuspend = (enableSoftwareSuspendHibernate ? enableSoftwareSuspendHibernate->isChecked():0); + laptop_portable::software_suspend_set_mask(enablesoftwaresuspend); + + config->setGroup("ApmDefault"); + + config->writeEntry("EnableStandby", enablestandby); + config->writeEntry("EnableSuspend", enablesuspend); + + config->setGroup("SoftwareSuspendDefault"); + config->writeEntry("EnableHibernate", enablesoftwaresuspend); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ApmConfig::load() +{ + load( false ); +} + +void ApmConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + config->setGroup("ApmDefault"); + enablestandby = config->readBoolEntry("EnableStandby", true); + enableStandby->setChecked(enablestandby); + enablesuspend = config->readBoolEntry("EnableSuspend", true); + enableSuspend->setChecked(enablesuspend); + config->setGroup("SoftwareSuspendDefault"); + enablesoftwaresuspend = config->readBoolEntry("EnableHibernate", false); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setChecked(enablesoftwaresuspend); + emit changed(useDefaults); +} + +void ApmConfig::defaults() +{ + load( true ); +} + + +void ApmConfig::configChanged() +{ + emit changed(true); +} + + +QString ApmConfig::quickHelp() const +{ + return i18n("<h1>APM Setup</h1>This module allows you to configure APM for your system"); +} + + +#include "apm.moc" + + diff --git a/klaptopdaemon/apm.h b/klaptopdaemon/apm.h new file mode 100644 index 0000000..a2213e9 --- /dev/null +++ b/klaptopdaemon/apm.h @@ -0,0 +1,71 @@ +/* + * apm.h + * + * Copyright (c) 2003 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __APMCONFIG_H__ +#define __APMCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class ApmConfig : public KCModule +{ + Q_OBJECT +public: + ApmConfig( QWidget *parent=0, const char* name=0); + ~ApmConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void setupHelper(); + void setupHelper2(); + +private: + KConfig *config; + + QCheckBox *enableSuspend; + QCheckBox *enableStandby; + QCheckBox *enableSoftwareSuspendHibernate; + bool enablestandby, enablesuspend, enablesoftwaresuspend; + const char *apm_name; +}; + +#endif + diff --git a/klaptopdaemon/applnk/.directory b/klaptopdaemon/applnk/.directory new file mode 100644 index 0000000..5099b09 --- /dev/null +++ b/klaptopdaemon/applnk/.directory @@ -0,0 +1,48 @@ +# KDE Config File +[KDE Desktop Entry] +Name=Laptop +Name[af]=Draagbare rekenaar +Name[az]=Dizüstü +Name[bg]=Лаптоп +Name[br]=Hezoug +Name[ca]=Portàtil +Name[cs]=Notebook +Name[cy]=Gliniadur +Name[da]=Bærbar +Name[de]=Notebook +Name[el]=Φορητό +Name[eo]=Portkomputilo +Name[es]=Portátil +Name[et]=Sülearvuti +Name[ga]=Ríomhaire Glúine +Name[gl]=Portátil +Name[hi]=लैपटॉप +Name[hu]=Noteszgép +Name[is]=Ferðavél +Name[it]=Computer portatile +Name[ja]=ラップトップ +Name[km]=កុំព្យួទ័រយួរដៃ +Name[ko]=랩탑 +Name[lv]=Laptops +Name[mk]=Лаптоп +Name[ms]=Komputer riba +Name[nds]=Klappreekner +Name[pt]=Portátil +Name[ru]=Батарея ноутбука +Name[sl]=Prenosnik +Name[sr]=Лаптоп +Name[sv]=Bärbar dator +Name[ta]= மடிக் கணினி +Name[tg]=Компютери Дастӣ +Name[th]=แลปทอป +Name[tr]=Dizüstü Bilgisayar +Name[uz@cyrillic]=Лаптоп +Name[ven]=Khomupwutha pfarwa +Name[wa]=Poirtåve +Name[xh]=Umphezulu osongiweyo +Name[zh_TW]=筆記型電腦 +Name[zu]=Ikhomputha eyisicaba ephathwayo +SortOrder=battery.desktop,bwarning.desktop,cwarning.desktop,power.desktop,pcmcia.desktop +Icon=laptop_settings +MiniIcon=laptop_settings + diff --git a/klaptopdaemon/applnk/Makefile.am b/klaptopdaemon/applnk/Makefile.am new file mode 100644 index 0000000..77274c7 --- /dev/null +++ b/klaptopdaemon/applnk/Makefile.am @@ -0,0 +1,4 @@ +xdg_apps_DATA = laptop.desktop pcmcia.desktop + +data3_DATA = klaptopdaemon.desktop +data3dir = $(kde_servicesdir)/kded diff --git a/klaptopdaemon/applnk/klaptopdaemon.desktop b/klaptopdaemon/applnk/klaptopdaemon.desktop new file mode 100644 index 0000000..0ba43cb --- /dev/null +++ b/klaptopdaemon/applnk/klaptopdaemon.desktop @@ -0,0 +1,116 @@ +[Desktop Entry] +Type=Service + +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=klaptopdaemon +X-KDE-FactoryName=klaptopdaemon +X-KDE-Kded-autoload=false +X-KDE-Kded-load-on-demand=true + +Icon=laptop_battery +DocPath=kcontrol/battery-monitor.html +Comment=Laptop battery monitor +Comment[ar]=مراقب بطّاريّة الحاسوب المحمول +Comment[bg]=Мониторинг на батериите на лаптоп +Comment[bs]=Nadzor baterije laptopa +Comment[ca]=Monitor de bateria de portàtils +Comment[cs]=Monitor baterií laptopu +Comment[da]=Batteriovervågning for bærbar +Comment[de]=Benachrichtigung über den Akku-Ladezustand +Comment[el]=Επόπτης μπαταρίας φορητού +Comment[eo]=Portkomputila baterimonitoro +Comment[es]=Monitor de batería del portátil +Comment[et]=Sülearvuti aku monitooring +Comment[eu]=Magalekoaren bateria begiralea +Comment[fa]=نمایشگر باتری رایانۀ کیفی +Comment[fi]=Kannettavan koneen akkutarkkailja +Comment[fr]=Indicateur de batterie de portable +Comment[ga]=Monatóir chadhnra ríomhaire glúine +Comment[he]=מד סוללה למחשב ברכיים +Comment[hu]=A telepek szintjelzője +Comment[is]=Rafhlöðueftirlit fyrir ferðavélar +Comment[it]=Controllo batteria computer portatile +Comment[ja]=ラップトップバッテリモニタ +Comment[ka]=ლეპტოპის კვების ელემენტის მონიტორი +Comment[kk]=Ноутбук аккумуляторын бақылау +Comment[km]=កម្មវិធីត្រួតពិនិត្យថ្មរបស់កុំព្យូទ័រយួរដៃ +Comment[lt]=Akumuliatoriaus stebėjimo priemonė +Comment[nb]=Batteriovervåker for bærbar maskin +Comment[nds]=Klappreekner-Batteriekieker +Comment[ne]=ल्यापटप ब्याट्री मोनिटर +Comment[nl]=Programma voor laptop-batterijbewaking +Comment[nn]=Batteriovervaking for bærbar maskin +Comment[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ ਨਿਗਰਾਨ +Comment[pl]=Kontrola stanu baterii laptopa +Comment[pt]=Monitor de bateria +Comment[pt_BR]=Monitor de bateria de laptop +Comment[ro]=Monitorează bateria laptop-ului +Comment[ru]=Монитор состояния батареи +Comment[sk]=Monitor nabitia bateriek +Comment[sl]=Nadzornik baterije za prenosnik +Comment[sr]=Надгледа батерију лаптопа +Comment[sr@Latn]=Nadgleda bateriju laptopa +Comment[sv]=Batterimonitor för bärbar dator +Comment[ta]= மடிக் கணினி மின்கலம் கண்காணிப்பாளன் +Comment[tr]=Dizüstü bilgisayarlar için pil izleyici +Comment[uk]=Монітор батарей лептопа +Comment[uz]=Laptopning batareyasini nazorat qilish +Comment[uz@cyrillic]=Лаптопнинг батареясини назорат қилиш +Comment[zh_CN]=便携电脑电池监视器 +Comment[zh_TW]=筆記型電腦電池監視器 +Name=Laptop Battery Monitor +Name[ar]=مراقب بطّاريّة الحاسوب المحمول +Name[bg]=Мониторинг на батериите +Name[bs]=Nadzor baterije laptopa +Name[ca]=Monitor de bateria de portàtils +Name[cs]=Monitor baterií laptopu +Name[cy]=Monitr Batri Gliniadur +Name[da]=Batteriovervågning for bærbar +Name[de]=Akku-Überwachung +Name[el]=Επόπτης μπαταρίας φορητού +Name[eo]=Portkomputila baterimonitoro +Name[es]=Monitor de batería del portátil +Name[et]=Sülearvuti aku monitooring +Name[eu]=Magalekoaren Bateria Begiralea +Name[fa]=نمایشگر باتری رایانۀ کیفی +Name[fi]=Akkutarkkailija +Name[fr]=Indicateur de batterie de portable +Name[ga]=Monatóir Chadhnra Ríomhaire Glúine +Name[he]=מד סוללה למחשב ברכיים +Name[hi]=लैपटॉप बैटरी मॉनीटर +Name[hu]=Feltöltöttségi szintjelző +Name[is]=Rafhlöðueftirlit fyrir ferðavélar +Name[it]=Controllo batteria portatile +Name[ja]=ラップトップバッテリモニタ +Name[ka]=ლეპტოპის კვების ელემენტის მონიტორი +Name[kk]=Ноутбук аккумуляторын бақылау +Name[km]=កម្មវិធីត្រួតពិនិត្យថ្មកុំព្យូទ័រយួរដៃ +Name[lt]=Akumuliatoriaus stebėjimo priemonė +Name[mk]=Монитор на батеријата на лаптопот +Name[ms]=Memerhatikan Bateri Komputer Riba +Name[nb]=Batteriovervåker for bærbar maskin +Name[nds]=Klappreekner-Batteriekieker +Name[ne]=ल्यापटप ब्याट्री मोनिटर +Name[nl]=Laptop-batterijbewaking +Name[nn]=Batteriovervakar for bærbar maskin +Name[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ ਨਿਗਰਾਨ +Name[pl]=Monitor baterii +Name[pt]=Monitor de Bateria +Name[pt_BR]=Monitor de Bateria de Laptop +Name[ro]=Monitor baterie de laptop +Name[ru]=Состояние батареи +Name[sk]=Monitor nabitia bateriek +Name[sl]=Nadzornik baterije za prenosnik +Name[sr]=Надгледање батерије лаптопа +Name[sr@Latn]=Nadgledanje baterije laptopa +Name[sv]=Batterimonitor för bärbar dator +Name[ta]= மடிக் கணினி மின்கலம் கண்காணி +Name[tg]=Дидабони Батареяи Компютери Дастӣ +Name[tr]=Dizüstü Pil Monitörü +Name[uk]=Монітор батарей +Name[uz]=Laptopning batareyasini nazorat qilish +Name[uz@cyrillic]=Лаптопнинг батареясини назорат қилиш +Name[wa]=Corwaitoe del batreye do poirtåve +Name[zh_CN]=便携电脑电池监视器 +Name[zh_TW]=筆記型電腦電池監視器 diff --git a/klaptopdaemon/applnk/laptop.desktop b/klaptopdaemon/applnk/laptop.desktop new file mode 100644 index 0000000..5c4101c --- /dev/null +++ b/klaptopdaemon/applnk/laptop.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +X-KDE-Library=laptop +X-KDE-FactoryName=laptop +X-KDE-Init=laptop +Exec=kcmshell laptop +Icon=laptop_battery +Type=Application +DocPath=kcontrol/laptop/index.html +Categories=Qt;KDE;X-KDE-settings-power; +Comment=Laptop Battery +Comment[af]=Draagbare rekenaar Batery +Comment[ar]=بطّاريّة الحاسوب المحمول +Comment[bg]=Мониторинг на батериите на лаптоп +Comment[br]=Pod-tredan an hezoug +Comment[bs]=Upozorenje istrošene baterije +Comment[ca]=Bateria de portàtil +Comment[cs]=Baterie notebooku +Comment[cy]=Batri Gliniadur +Comment[da]=Batteri for bærbar +Comment[de]=Notebook-Akku +Comment[el]=Μπαταρία φορητού +Comment[eo]=Avertilo por maplenigo de la baterio +Comment[es]=Batería del portátil +Comment[et]=Sülearvuti aku +Comment[eu]=Magalekoen Bateria +Comment[fa]=باتری رایانۀ کیفی +Comment[fi]=Kannettavan akku +Comment[fr]=Batterie d'ordinateur portable +Comment[ga]=Cadhnra Ríomhaire Glúine +Comment[he]=סוללת מחשב נייד +Comment[hi]=लैपटॉप बैटरी +Comment[hr]=Baterija laptopa +Comment[hu]=Energiakezelési beállítások noteszgép esetén +Comment[is]=Rafhlaða ferðavélar +Comment[it]=Batteria computer portatile +Comment[ja]=ラップトップバッテリ +Comment[ka]=ლეპტოპის კვების ელემენტი +Comment[kk]=Ноутбуктің аккумуляторы +Comment[km]=ថ្មកុំព្យូទ័រយួរដៃ +Comment[lt]=Nešiojamo kompiuterio akumuliatorius +Comment[mk]=Предупредува кога батеријата е слаба +Comment[ms]=Bateri Komputer Riba +Comment[mt]=Batterija tal-laptop +Comment[nb]=Batteri til bærbar maskin +Comment[nds]=Klappreekner-Batterie +Comment[ne]=ल्यापटप ब्याट्री +Comment[nl]=Laptopbatterij +Comment[nn]=Batteri til bærbar +Comment[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ +Comment[pl]=Ostrzeżenie o słabych bateriach +Comment[pt]=Bateria do portátil +Comment[pt_BR]=Bateria do Laptop +Comment[ro]=Baterie de laptop +Comment[ru]=Батарея ноутбука +Comment[sk]=Batérie laptopu +Comment[sl]=Baterija prenosnika +Comment[sr]=Батерија лаптопа +Comment[sr@Latn]=Baterija laptopa +Comment[sv]=Batteri för bärbar dator +Comment[ta]= மடிக் கணினி மின்கலம் +Comment[tg]=Батареяи Компютери Дастӣ +Comment[th]=แบตเตอรีของเครื่องแลปทอบ +Comment[tr]=Dizüstü Pili +Comment[uk]=Батареї лептопа +Comment[uz]=Laptopning batareyasi +Comment[uz@cyrillic]=Лаптопнинг батареяси +Comment[wa]=Batreye do poirtåve +Comment[xh]=Ibhetri ye Laptop +Comment[zh_CN]=便携电脑电池 +Comment[zh_TW]=筆記型電腦的電池 +Comment[zu]=Ibhetri Yekhomputha eyisicaba ephathwayo +Name=Laptop Battery +Name[af]=Draagbare rekenaar Batery +Name[ar]=بطّاريّة الحاسوب المحمول +Name[bg]=Батерии на лаптоп +Name[br]=Pod-tredan an hezoug +Name[bs]=Laptop baterija +Name[ca]=Bateria de portàtil +Name[cs]=Baterie notebooku +Name[cy]=Batri Gliniadur +Name[da]=Batteri for bærbar +Name[de]=Notebook-Akku +Name[el]=Μπαταρία φορητού +Name[eo]=Portkomputila baterio +Name[es]=Batería del portátil +Name[et]=Sülearvuti aku +Name[eu]=Magalekoen Bateria +Name[fa]=باتری رایانۀ کیفی +Name[fi]=Kannettavan akku +Name[fr]=Batterie d'ordinateur portable +Name[ga]=Cadhnra Ríomhaire Glúine +Name[he]=סוללת מחשב נייד +Name[hi]=लैपटॉप बैटरी +Name[hr]=Laptop baterija +Name[hu]=Noteszgép-telepek +Name[is]=Ferðavélarafhlaða +Name[it]=Batteria computer portatile +Name[ja]=ラップトップバッテリ +Name[ka]=ლეპტოპის კვების ელემენტი +Name[kk]=Ноутбуктің аккумуляторы +Name[km]=ថ្មកុំព្យូទ័រយួរដៃ +Name[lt]=Laptop baterija +Name[mk]=Батерија на лаптопот +Name[ms]=Bateri Komputer Riba +Name[mt]=Batterija tal-laptop +Name[nb]=Batteri til bærbar maskin +Name[nds]=Klappreekner-Batterie +Name[ne]=ल्यापटप ब्याट्री +Name[nl]=Laptopbatterij +Name[nn]=Batteri til bærbar +Name[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ +Name[pl]=Bateria laptopa +Name[pt]=Bateria do Portátil +Name[pt_BR]=Bateria do Laptop +Name[ro]=Baterie laptop +Name[ru]=Батарея ноутбука +Name[sk]=Batérie laptopu +Name[sl]=Baterija prenosnika +Name[sr]=Батерија лаптопа +Name[sr@Latn]=Baterija laptopa +Name[sv]=Batteri för bärbar dator +Name[ta]= மடிக் கணினி மின்கலம் +Name[tg]=Батареяи Компютери Дастӣ +Name[th]=แบตเตอรีแลปทอบ +Name[tr]=Dizüstü Pili +Name[uk]=Батареї лептопа +Name[uz]=Laptopning batareyasi +Name[uz@cyrillic]=Лаптопнинг батареяси +Name[wa]=Batreye do poirtåve +Name[xh]=Ibhetri ye Laptop +Name[zh_CN]=便携电脑电池 +Name[zh_TW]=筆記型電腦的電池 +Name[zu]=Ibhetri Yekhomputha eyisicaba ephathwayo +Init=klaptop_check + diff --git a/klaptopdaemon/applnk/pcmcia.desktop b/klaptopdaemon/applnk/pcmcia.desktop new file mode 100644 index 0000000..0b1249a --- /dev/null +++ b/klaptopdaemon/applnk/pcmcia.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +X-KDE-ModuleType=Library +X-KDE-Library=laptop +X-KDE-FactoryName=pcmcia +Exec=kcmshell pcmcia +Icon=laptop_pcmcia +Type=Application +DocPath=kinfocenter/pcmcia/index.html +Comment=PCMCIA status +Comment[af]=Pcmcia status +Comment[ar]=حالة بطاقة PCMCIA +Comment[az]=PCMCIA vəziyyəti +Comment[bg]=Информация за PCMCIA +Comment[br]=Saviad PCMCIA +Comment[ca]=Estat de PCMCIA +Comment[cs]=Stav PCMCIA +Comment[cy]=Statws PCMCIA +Comment[da]=PCMCIA-status +Comment[de]=PCMCIA-Status +Comment[el]=Κατάσταση PCMCIA +Comment[eo]=PCMCIA-stato +Comment[es]=Estado PCMCIA +Comment[et]=PCMCIA olek +Comment[eu]=PCMCIAren egoera +Comment[fa]=PCMCIA وضعیت +Comment[fi]=PCMCIA-tila +Comment[fr]=État PCMCIA +Comment[ga]=Stádas PCMCIA +Comment[gl]=Estado de PCMCIA +Comment[he]=מידע על מצב PCMCIA +Comment[hi]=पीसीएमसीआईए स्थिति +Comment[hr]=Stanje PCMCIA +Comment[hu]=PCMCIA-állapot +Comment[id]=Status PCMCIA +Comment[is]=PCMCIA staða +Comment[it]=Stato PCMCIA +Comment[ja]=PCMCIA の状態 +Comment[ka]=PCMCIA სტატუსი +Comment[kk]=PCMCIA күйі +Comment[km]=ស្ថានភាព PCMCIA +Comment[ko]=PCMCIA 현재 상태 +Comment[lt]=PCMCIA būsena +Comment[mk]=Статус на PCMCIA +Comment[ms]=Status PCMCIA +Comment[mt]=Stat PCMCIA +Comment[nb]=PCMCIA-status +Comment[nds]=PCMCIA-Status +Comment[ne]=PCMCIA स्थिति +Comment[nl]=Status van PCMCIA +Comment[nn]=PCMCIA-status +Comment[pa]=PCMCIA ਹਾਲਤ +Comment[pl]=Status kart PCMCIA +Comment[pt]=Estado do PCMCIA +Comment[pt_BR]=Estado do PCMCIA +Comment[ro]=Starea PCMCIA +Comment[ru]=Состояние PCMCIA +Comment[sk]=stav PCMCIA +Comment[sl]=Stanje PCMCIA +Comment[sr]=Статус PCMCIA уређаја +Comment[sr@Latn]=Status PCMCIA uređaja +Comment[sv]=PCMCIA-status +Comment[ta]=PCMCIA நிலை +Comment[tg]=Ҳолати PCMCIA +Comment[th]=สถานะอุปกรณ์ PCMCIA +Comment[tr]=PCMCIA durumu +Comment[uk]=Стан PCMCIA +Comment[uz]=PCMCIA holati +Comment[uz@cyrillic]=PCMCIA ҳолати +Comment[ven]=Maimo a PCMCIA +Comment[vi]=Trạng thái PCMCIA +Comment[wa]=Estat do PCMCIA +Comment[xh]=Indawo esemthethweni ye PCMCIA +Comment[zh_CN]=PCMCIA 状态 +Comment[zh_TW]=PCMCIA 狀態 +Comment[zu]=Izinga le-PCMCIA +Name=PCMCIA +Name[af]=Pcmcia +Name[he]=מצב PCMCIA +Name[hi]=पीसीएमसीआईए +Name[pt_BR]=Cartões PCMCIA +Name[ta]= PCMCIA +Name[th]=อุปกรณ์ PCMCIA + +Categories=Qt;KDE;X-KDE-information; diff --git a/klaptopdaemon/battery.cpp b/klaptopdaemon/battery.cpp new file mode 100644 index 0000000..ef43890 --- /dev/null +++ b/klaptopdaemon/battery.cpp @@ -0,0 +1,390 @@ +/* + * battery.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * Copyright (c) 2006 Flavio Castelli <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "battery.h" +#include "version.h" +#include "portable.h" + +// other KDE headers: +#include <klocale.h> +#include <kconfig.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <krichtextlabel.h> + +// other Qt headers: +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qhgroupbox.h> +#include <qgrid.h> +#include <qpushbutton.h> +#include <qtooltip.h> +extern void wake_laptop_daemon(); + + +BatteryConfig::BatteryConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + editPoll(0), + iconloader(0), + buttonNoBattery(0), + buttonNoCharge(0), + buttonCharge(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + instance = new KInstance("klaptopdaemon"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + // do we show the monitor + runMonitor = new QCheckBox( i18n("&Show battery monitor"), this ); + top_layout->addWidget( runMonitor ); + QToolTip::add( runMonitor, i18n( "This box enables the battery state icon in the panel" ) ); + connect( runMonitor, SIGNAL(clicked()), this, SLOT(configChanged()) ); + connect( runMonitor, SIGNAL(clicked()), this, SLOT(runMonitorChanged()) ); + + // show also the battery level percentage + showLevel = new QCheckBox( i18n("Show battery level percentage"), this ); + top_layout->addWidget( showLevel ); + QToolTip::add( showLevel, i18n( "This box enables a text message near the battery state icon containing battery level percentage" ) ); + connect( showLevel, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + notifyMe = new QCheckBox( i18n("&Notify me whenever my battery becomes fully charged"), this ); + top_layout->addWidget( notifyMe ); + QToolTip::add( notifyMe, i18n( "This box enables a dialog box that pops up when your battery becomes fully charged" ) ); + connect( notifyMe, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + blankSaver = new QCheckBox( i18n("&Use a blank screen saver when running on battery"), this ); + top_layout->addWidget( blankSaver ); + connect( blankSaver, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + if (!apm) { + top_layout->addWidget( laptop_portable::no_power_management_explanation(this) ); + } else { + iconloader = new KIconLoader("klaptopdaemon"); + + // the poll time (in seconds) + QHBox *hb = new QHBox( this ); + hb->setSpacing( KDialog::spacingHint() ); + top_layout->addWidget( hb ); + + QLabel* poll_label = new QLabel( i18n("&Check status every:"), hb ); + editPoll = new QSpinBox( 1, 3600, 1, hb ); // min,max,step + QToolTip::add( editPoll, i18n( "Choose how responsive the laptop software will be when it checks the battery status" ) ); + editPoll->setSuffix( i18n("keep short, unit in spinbox", "sec") ); + poll_label->setBuddy( editPoll ); + connect( editPoll, SIGNAL(valueChanged(int)), + this, SLOT(configChanged()) ); + QWidget* spacer = new QWidget( hb ); + hb->setStretchFactor( spacer, 1 ); + + // group box to hold the icons together + QVGroupBox* icons_groupbox = new QVGroupBox( i18n("Select Battery Icons"), this ); + icons_groupbox->layout()->setSpacing( KDialog::spacingHint() ); + top_layout->addWidget( icons_groupbox, 0, Qt::AlignLeft ); + + // layout to hold the icons inside the groupbox + QGrid *icon_grid = new QGrid( 3 /*cols*/, icons_groupbox ); + icon_grid->setSpacing( KDialog::spacingHint() ); + + buttonNoBattery = new KIconButton( iconloader, icon_grid ); + buttonNoCharge = new KIconButton( iconloader, icon_grid ); + buttonCharge = new KIconButton( iconloader, icon_grid ); + (void)new QLabel( buttonNoBattery, i18n("No &battery"), icon_grid); + (void)new QLabel( buttonNoCharge, i18n("&Not charging"), icon_grid); + (void)new QLabel( buttonCharge, i18n("Char&ging"), icon_grid); + buttonNoBattery->setIconType( KIcon::NoGroup, KIcon::Any, 1); + buttonNoCharge->setIconType( KIcon::NoGroup, KIcon::Any, 1); + buttonCharge->setIconType( KIcon::NoGroup, KIcon::Any, 1); + connect(buttonNoBattery, SIGNAL(iconChanged(QString)), this, SLOT(iconChanged())); + connect(buttonNoCharge, SIGNAL(iconChanged(QString)), this, SLOT(iconChanged())); + connect(buttonCharge, SIGNAL(iconChanged(QString)), this, SLOT(configChanged())); + + + int num_batteries; + QStringList battery_names, battery_states, battery_values; + laptop_portable::get_battery_status(num_batteries, battery_names, battery_states, battery_values); + if (num_batteries > 0) { + QHBoxLayout *hl = new QHBoxLayout(); + top_layout->addLayout(hl); + + QHGroupBox *hb = new QHGroupBox(i18n("Current Battery Status"), this); + for (int i = 0; i < num_batteries; i++) { + + QWidget *wp; + if (num_batteries == 1) { + wp = new QWidget(hb); + } else { + wp = new QVGroupBox(battery_names[i], hb); + } + QVBoxLayout *vb = new QVBoxLayout(wp); + + QLabel *l; + + l = new QLabel(wp); // icon indicating state + vb->addWidget(l); + batt_label_1.append(l); + + l = new QLabel(QString(""), wp); + vb->addWidget(l); + batt_label_2.append(l); + + l = new QLabel(QString(""), wp); + vb->addWidget(l); + batt_label_3.append(l); + } + hl->addWidget(hb); + hl->addStretch(1); + (void)startTimer(30*1000); // update 2x every minute + } + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* explain = new KRichTextLabel( i18n("This panel controls whether the battery status monitor\nappears in the system tray and what it looks like.").replace("\n"," "), this); + top_layout->addWidget(explain, 0); + laptop_portable::extra_config(this, config, top_layout); + } + + top_layout->addStretch(1); + startMonitor = new QPushButton( i18n("&Start Battery Monitor"), this); + connect(startMonitor, SIGNAL(clicked()), this, SLOT(slotStartMonitor())); + top_layout->addWidget( startMonitor, 0, Qt::AlignRight ); + + load(); +} + +BatteryConfig::~BatteryConfig() +{ + delete instance; + delete config; +} + + +void BatteryConfig::save() +{ + enablemonitor = runMonitor->isChecked(); + showlevel = showLevel->isChecked(); + useblanksaver = blankSaver->isChecked(); + notifyme = notifyMe->isChecked(); + + if (apm) { + poll_time = editPoll->value(); + nobattery = buttonNoBattery->icon(); + chargebattery = buttonCharge->icon(); + nochargebattery = buttonNoCharge->icon(); + } + config->setGroup("BatteryDefault"); + + config->writeEntry("Enable", enablemonitor); + config->writeEntry("ShowLevel", showlevel); + config->writeEntry("NotifyMe", notifyme); + config->writeEntry("BlankSaver", useblanksaver); + config->writeEntry("Poll", poll_time); + config->writeEntry("NoBatteryPixmap", nobattery); + config->writeEntry("ChargePixmap", chargebattery); + config->writeEntry("NoChargePixmap", nochargebattery); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void BatteryConfig::load() +{ + load( false ); +} + +void BatteryConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + config->setGroup("BatteryDefault"); + + poll_time = config->readNumEntry("Poll", 20); + enablemonitor = config->readBoolEntry("Enable", true); + showlevel = config->readBoolEntry("ShowLevel", false); + notifyme = config->readBoolEntry("NotifyMe", false); + useblanksaver = config->readBoolEntry("BlankSaver", false); + + nobattery = config->readEntry("NoBatteryPixmap", "laptop_nobattery"); + nochargebattery = config->readEntry("NoChargePixmap", "laptop_nocharge"); + chargebattery = config->readEntry("ChargePixmap", "laptop_charge"); + + runMonitor->setChecked(enablemonitor); + showLevel->setChecked(showlevel); + blankSaver->setChecked(useblanksaver); + notifyMe->setChecked(notifyme); + if (apm) { + editPoll->setValue(poll_time); + buttonNoCharge->setIcon(nochargebattery); + buttonCharge->setIcon(chargebattery); + buttonNoBattery->setIcon(nobattery); + } + battery_pm = SmallIcon(nochargebattery, 20, KIcon::DefaultState, instance); + battery_nopm = SmallIcon(nobattery, 20, KIcon::DefaultState, instance); + emit changed(useDefaults); + BatteryStateUpdate(); +} + +void BatteryConfig::defaults() +{ + load( true ); +} + +void BatteryConfig::runMonitorChanged() +{ + showLevel->setEnabled (runMonitor->isChecked()); +} + +void BatteryConfig::configChanged() +{ + emit changed(true); +} + + +QString BatteryConfig::quickHelp() const +{ + return i18n("<h1>Laptop Battery</h1>This module allows you to monitor " + "your batteries. To make use of this module, you must have power management system software " + "installed. (And, of course, you should have batteries in your machine.)"); +} + + +void BatteryConfig::slotStartMonitor() +{ + wake_laptop_daemon(); + if (!enablemonitor) { + KMessageBox::information(0, i18n("<qt>The battery monitor has been started, but the tray icon is currently disabled. You can make it appear by selecting the <b>Show battery monitor</b> entry on this page and applying your changes.</qt>"), QString::null, "howToEnableMonitor"); + } +} + +void +BatteryConfig::ConvertIcon(int percent, QPixmap &pm, QPixmap &result) +{ + QImage image = pm.convertToImage(); + + int w = image.width(); + int h = image.height(); + int count = 0; + QRgb rgb; + int x, y; + for (x = 0; x < w; x++) + for (y = 0; y < h; y++) { + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) + count++; + } + int c = (count*percent)/100; + if (percent == 100) { + c = count; + } else + if (percent != 100 && c == count) + c = count-1; + + + if (c) { + uint ui; + QRgb blue = qRgb(0x00,0x00,0xff); + + if (image.depth() <= 8) { + ui = image.numColors(); // this fix thanks to Sven Krumpke + image.setNumColors(ui+1); + image.setColor(ui, blue); + } else { + ui = 0xff000000|blue; + } + + for (y = h-1; y >= 0; y--) + for (x = 0; x < w; x++) { + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) { + image.setPixel(x, y, ui); + c--; + if (c <= 0) + goto quit; + } + } + } +quit: + + result.convertFromImage(image); +} + +void +BatteryConfig::BatteryStateUpdate() +{ + int num_batteries; + QStringList battery_names, battery_states, battery_values; + laptop_portable::get_battery_status(num_batteries, battery_names, battery_states, battery_values); + if (num_batteries > 0) { + for (int i = 0; i < num_batteries; i++) { + if (battery_states[i] == "yes") { + QPixmap result; + ConvertIcon(battery_values[i].toInt(), battery_pm, result); + batt_label_1.at(i)->setPixmap(result); + + batt_label_2.at(i)->setText(battery_values[i]+"%"); + + batt_label_3.at(i)->setText(i18n("Present")); + } else { + batt_label_1.at(i)->setPixmap(battery_nopm); + + batt_label_2.at(i)->setText(""); + + batt_label_3.at(i)->setText(i18n("Not present")); + } + } + } +} + +void BatteryConfig::iconChanged() +{ + nobattery = buttonNoBattery->icon(); + nochargebattery = buttonNoCharge->icon(); + battery_pm = SmallIcon(nochargebattery, 20, KIcon::DefaultState, instance); + battery_nopm = SmallIcon(nobattery, 20, KIcon::DefaultState, instance); + emit changed(true); + BatteryStateUpdate(); +} + +void BatteryConfig::timerEvent(QTimerEvent *) +{ + BatteryStateUpdate(); +} + +#include "battery.moc" + + diff --git a/klaptopdaemon/battery.h b/klaptopdaemon/battery.h new file mode 100644 index 0000000..3e484ef --- /dev/null +++ b/klaptopdaemon/battery.h @@ -0,0 +1,100 @@ +/* + * battery.h + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * Copyright (c) 2006 Flavio Castelli <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BATTERYCONFIG_H__ +#define __BATTERYCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> +#include <qpixmap.h> +#include <qptrlist.h> + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; +class QLabel; + + +class BatteryConfig : public KCModule +{ + Q_OBJECT +public: + BatteryConfig( QWidget *parent=0, const char* name=0); + ~BatteryConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void runMonitorChanged(); + void slotStartMonitor(); + void iconChanged(); + void BatteryStateUpdate(); + +private: + void timerEvent(QTimerEvent *); + void ConvertIcon(int percent, QPixmap &pm, QPixmap &result); + KConfig *config; + + QSpinBox* editPoll; + QCheckBox* runMonitor; + QCheckBox* showLevel; + QCheckBox* notifyMe; + QCheckBox* blankSaver; + bool enablemonitor; + bool showlevel; + bool enablequitmenu; + bool useblanksaver; + bool notifyme; + + KIconLoader *iconloader; + + KIconButton *buttonNoBattery; + KIconButton *buttonNoCharge; + KIconButton *buttonCharge; + QString nobattery, nochargebattery, chargebattery; + QPushButton *startMonitor; + bool apm; + int poll_time; + + QPtrList<QLabel> batt_label_1, batt_label_2, batt_label_3; + QPixmap battery_pm, battery_nopm; + + KInstance *instance; +}; + +#endif + diff --git a/klaptopdaemon/buttons.cpp b/klaptopdaemon/buttons.cpp new file mode 100644 index 0000000..f9ccce4 --- /dev/null +++ b/klaptopdaemon/buttons.cpp @@ -0,0 +1,620 @@ +/* + * buttons.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "buttons.h" +#include "portable.h" +#include "version.h" + +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <knumvalidator.h> +#include <kdialog.h> +#include <kapplication.h> +#include <kcombobox.h> + +#include <qlayout.h> +#include <qvbuttongroup.h> +#include <qspinbox.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qslider.h> +#include <qtooltip.h> +extern void wake_laptop_daemon(); + +ButtonsConfig::ButtonsConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + lidBox(0), + lidStandby(0), + lidSuspend(0), + lidOff(0), + lidHibernate(0), + lidShutdown(0), + lidLogout(0), + lidBrightness(0), + lidValBrightness(0), + lidThrottle(0), + lidValThrottle(0), + lidPerformance(0), + lidValPerformance(0), + + powerBox(0), + powerStandby(0), + powerSuspend(0), + powerOff(0), + powerHibernate(0), + powerShutdown(0), + powerLogout(0), + powerBrightness(0), + powerValBrightness(0), + powerThrottle(0), + powerValThrottle(0), + powerPerformance(0), + powerValPerformance(0) +{ + int can_shutdown = 1; // fix me + int can_logout = 1; // fix me + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + int can_brightness = laptop_portable::has_brightness(); + QStringList throttle_list; + int current_throttle; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + QStringList performance_list; + int current_performance; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + + if (!apm && !can_brightness && !has_throttle && !has_performance) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + + if (!can_standby && !can_suspend && !can_hibernate && !can_brightness && !has_throttle && !has_performance) + apm = 0; + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + QLabel* explain = laptop_portable::how_to_do_suspend_resume(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + QHBoxLayout *hlay = new QHBoxLayout( top_layout ); + + if (laptop_portable::has_button(laptop_portable::LidButton)) { + lidBox = new QVButtonGroup(i18n("Lid Switch Closed"), this); + lidBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( lidBox, i18n( "Select which actions will occur when the laptop's lid is closed" ) ); + hlay->addWidget( lidBox ); + + if (can_standby) { + lidStandby = new QRadioButton(i18n("Standb&y"), lidBox); + QToolTip::add( lidStandby, i18n( "Causes the laptop to move into the standby temporary low-power state" ) ); + } + if (can_suspend) { + lidSuspend = new QRadioButton(i18n("&Suspend"), lidBox); + QToolTip::add( lidSuspend, i18n( "Causes the laptop to move into the suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + lidHibernate = new QRadioButton(i18n("H&ibernate"), lidBox); + QToolTip::add( lidHibernate, i18n( "Causes the laptop to move into the hibernate 'save-to-disk' state" ) ); + } + if (can_shutdown) { + lidShutdown = new QRadioButton(i18n("System power off"), lidBox); + QToolTip::add( lidShutdown, i18n( "Causes the laptop to power down" ) ); + } + if (can_logout) { + lidLogout = new QRadioButton(i18n("Logout"), lidBox); + QToolTip::add( lidShutdown, i18n( "Causes you to be logged out" ) ); + } + if (can_suspend||can_standby||can_hibernate||can_shutdown||can_logout) + lidOff = new QRadioButton(i18n("&Off"), lidBox); + if (can_brightness) { + lidBrightness = new QCheckBox(i18n("Brightness"), lidBox); + QToolTip::add( lidBrightness, i18n( "Causes the back panel brightness to be set" ) ); + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + lidValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + lidValBrightness->setEnabled(0); + QToolTip::add( lidValBrightness, i18n( "How bright the back panel will be set to" ) ); + connect (lidValBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(lidValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + lidPerformance = new QCheckBox(i18n("System performance"), lidBox); + QToolTip::add( lidPerformance, i18n( "Causes the performance profile to be changed" ) ); + + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + lidValPerformance = new KComboBox(0, wp); + QToolTip::add( lidValPerformance, i18n( "The performance profile to switch to" ) ); + lidValPerformance->insertStringList(performance_list); + lidValPerformance->setEnabled(0); + connect (lidValPerformance, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(lidValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + lidThrottle = new QCheckBox(i18n("CPU throttle"), lidBox); + QToolTip::add( lidThrottle, i18n( "Causes the CPU to be throttled back" ) ); + + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + lidValThrottle = new KComboBox(0, wp); + QToolTip::add( lidValThrottle, i18n( "How much to throttle back the CPU" ) ); + lidValThrottle->insertStringList(throttle_list); + lidValThrottle->setEnabled(0); + connect (lidValThrottle, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(lidValThrottle); + xl->addStretch(1); + + + } + connect(lidBox, SIGNAL(clicked(int)), this, SLOT(configChanged())); + } + + if (laptop_portable::has_button(laptop_portable::PowerButton)) { + + powerBox = new QVButtonGroup(i18n("Power Switch Pressed"), this); + powerBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( powerBox, i18n( "Select which actions will occur when the laptop's power button is pressed" ) ); + hlay->addWidget( powerBox ); + + if (can_standby) { + powerStandby = new QRadioButton(i18n("Sta&ndby"), powerBox); + QToolTip::add( powerStandby, i18n( "Causes the laptop to move into the standby temporary low-power state" ) ); + } + if (can_suspend) { + powerSuspend = new QRadioButton(i18n("S&uspend"), powerBox); + QToolTip::add( powerSuspend, i18n( "Causes the laptop to move into the suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + powerHibernate = new QRadioButton(i18n("Hi&bernate"), powerBox); + QToolTip::add( powerHibernate, i18n( "Causes the laptop to move into the hibernate 'save-to-disk' state" ) ); + } + if (can_shutdown) { + powerShutdown = new QRadioButton(i18n("System power off"), powerBox); + QToolTip::add( powerShutdown, i18n( "Causes the laptop to power down" ) ); + } + if (can_logout) { + powerLogout = new QRadioButton(i18n("Logout"), powerBox); + QToolTip::add( powerShutdown, i18n( "Causes you to be logged out" ) ); + } + if (can_suspend||can_standby||can_hibernate||can_shutdown||can_logout) + powerOff = new QRadioButton(i18n("O&ff"), powerBox); + if (can_brightness) { + powerBrightness = new QCheckBox(i18n("Brightness"), powerBox); + QToolTip::add( powerBrightness, i18n( "Causes the back panel brightness to be set" ) ); + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + powerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( powerValBrightness, i18n( "How bright the back panel will be set to" ) ); + powerValBrightness->setEnabled(0); + connect (powerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(powerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + powerPerformance = new QCheckBox(i18n("System performance"), powerBox); + QToolTip::add( powerPerformance, i18n( "Causes the performance profile to be changed" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValPerformance = new KComboBox(0, wp); + QToolTip::add( powerValPerformance, i18n( "The performance profile to switch to" ) ); + powerValPerformance->insertStringList(performance_list); + powerValPerformance->setEnabled(0); + connect (powerValPerformance, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(powerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + powerThrottle = new QCheckBox(i18n("CPU throttle"), powerBox); + QToolTip::add( powerThrottle, i18n( "Causes the CPU to be throttled back" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValThrottle = new KComboBox(0, wp); + QToolTip::add( powerValThrottle, i18n( "How much to throttle back the CPU" ) ); + powerValThrottle->insertStringList(throttle_list); + powerValThrottle->setEnabled(0); + connect (powerValThrottle, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(powerValThrottle); + xl->addStretch(1); + } + connect(powerBox, SIGNAL(clicked(int)), this, SLOT(configChanged())); + } + + hlay->addStretch(1); + + QLabel* explain = new QLabel(i18n("This panel enables actions that are triggered when the lid closure switch " + "or power switch on your laptop is pressed. Some laptops may already " + "automatically do things like this, if you cannot disable them in your BIOS " + "you probably should not enable anything in this panel."), this); + explain->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this ), 0, Qt::AlignRight ); + } + } + + load(); +} + +ButtonsConfig::~ButtonsConfig() +{ + delete config; +} + +void ButtonsConfig::save() +{ + power = getPower(); + lid = getLid(); + lid_bright_enabled = (lidBrightness?lidBrightness->isChecked():0); + power_bright_enabled = (powerBrightness?powerBrightness->isChecked():0); + lid_bright_val = (lidValBrightness?lidValBrightness->value():0); + power_bright_val = (powerValBrightness?powerValBrightness->value():0); + lid_performance_enabled = (lidPerformance?lidPerformance->isChecked():0); + power_performance_enabled = (powerPerformance?powerPerformance->isChecked():0); + lid_performance_val = (lidValPerformance?lidValPerformance->currentText():""); + power_performance_val = (powerValPerformance?powerValPerformance->currentText():""); + lid_throttle_enabled = (lidThrottle?lidThrottle->isChecked():0); + power_throttle_enabled = (powerThrottle?powerThrottle->isChecked():0); + lid_throttle_val = (lidValThrottle?lidValThrottle->currentText():""); + power_throttle_val = (powerValThrottle?powerValThrottle->currentText():""); + + config->setGroup("LaptopButtons"); + config->writeEntry("LidSuspend", lid); + config->writeEntry("PowerSuspend", power); + config->writeEntry("PowerBrightnessEnabled", power_bright_enabled); + config->writeEntry("LidBrightnessEnabled", lid_bright_enabled); + config->writeEntry("PowerBrightness", power_bright_val); + config->writeEntry("LidBrightness", lid_bright_val); + config->writeEntry("PowerPerformanceEnabled", power_performance_enabled); + config->writeEntry("LidPerformanceEnabled", lid_performance_enabled); + config->writeEntry("PowerPerformance", power_performance_val); + config->writeEntry("LidPerformance", lid_performance_val); + config->writeEntry("PowerThrottleEnabled", power_throttle_enabled); + config->writeEntry("LidThrottleEnabled", lid_throttle_enabled); + config->writeEntry("PowerThrottle", power_throttle_val); + config->writeEntry("LidThrottle", lid_throttle_val); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ButtonsConfig::load() +{ + load( false ); +} + +void ButtonsConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("LaptopButtons"); + lid = config->readNumEntry("LidSuspend", 0); + power = config->readNumEntry("PowerSuspend", 0); + lid_bright_enabled = config->readBoolEntry("LidBrightnessEnabled", 0); + power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0); + lid_bright_val = config->readNumEntry("LidBrightness", 0); + power_bright_val = config->readNumEntry("PowerBrightness", 0); + lid_performance_enabled = config->readBoolEntry("LidPerformanceEnabled", 0); + power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0); + lid_performance_val = config->readEntry("LidPerformance", ""); + power_performance_val = config->readEntry("PowerPerformance", ""); + lid_throttle_enabled = config->readBoolEntry("LidThrottleEnabled", 0); + power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0); + lid_throttle_val = config->readEntry("LidThrottle", ""); + power_throttle_val = config->readEntry("PowerThrottle", ""); + + // the GUI should reflect the real values + setPower(power, lid); + if (lidBrightness) + lidBrightness->setChecked(lid_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (lidValBrightness) { + lidValBrightness->setValue(lid_bright_val); + lidValBrightness->setEnabled(lid_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + if (lidPerformance) + lidPerformance->setChecked(lid_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (lidValPerformance) { + int ind = 0; + for (int i = 0; i < lidValPerformance->count(); i++) + if (lidValPerformance->text(i) == lid_performance_val) { + ind = i; + break; + } + lidValPerformance->setCurrentItem(ind); + lidValPerformance->setEnabled(lid_performance_enabled); + } + if (powerValPerformance) { + int ind = 0; + for (int i = 0; i < powerValPerformance->count(); i++) + if (powerValPerformance->text(i) == power_performance_val) { + ind = i; + break; + } + powerValPerformance->setCurrentItem(ind); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (lidThrottle) + lidThrottle->setChecked(lid_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (lidValThrottle) { + int ind = 0; + for (int i = 0; i < lidValThrottle->count(); i++) + if (lidValThrottle->text(i) == lid_throttle_val) { + ind = i; + break; + } + lidValThrottle->setCurrentItem(ind); + lidValThrottle->setEnabled(lid_throttle_enabled); + } + if (powerValThrottle) { + int ind = 0; + for (int i = 0; i < powerValThrottle->count(); i++) + if (powerValThrottle->text(i) == power_throttle_val) { + ind = i; + break; + } + powerValThrottle->setCurrentItem(ind); + powerValThrottle->setEnabled(power_throttle_enabled); + } + emit changed( useDefaults ); +} + +void ButtonsConfig::defaults() +{ + setPower(0, 0); + lid_bright_enabled = 0; + power_bright_enabled = 0; + lid_bright_val = 0; + power_bright_val = 0; + lid_performance_enabled = 0; + power_performance_enabled = 0; + lid_performance_val = ""; + power_performance_val = ""; + lid_throttle_enabled = 0; + power_throttle_enabled = 0; + lid_throttle_val = ""; + power_throttle_val = ""; + if (lidBrightness) + lidBrightness->setChecked(lid_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (lidValBrightness) { + lidValBrightness->setValue(lid_bright_val); + lidValBrightness->setEnabled(lid_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + + + if (lidPerformance) + lidPerformance->setChecked(lid_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (lidValPerformance) { + lidValPerformance->setCurrentItem(0); + lidValPerformance->setEnabled(lid_performance_enabled); + } + if (powerValPerformance) { + powerValPerformance->setCurrentItem(0); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (lidThrottle) + lidThrottle->setChecked(lid_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (lidValThrottle) { + lidValThrottle->setCurrentItem(0); + lidValThrottle->setEnabled(lid_throttle_enabled); + } + if (powerValThrottle) { + powerValThrottle->setCurrentItem(0); + powerValThrottle->setEnabled(power_throttle_enabled); + } +} + +int ButtonsConfig::getLid() +{ + if (!apm) + return(lid); + if (lidHibernate && lidHibernate->isChecked()) + return 3; + if (lidStandby && lidStandby->isChecked()) + return 1; + if (lidSuspend && lidSuspend->isChecked()) + return 2; + if (lidLogout && lidLogout->isChecked()) + return 4; + if (lidShutdown && lidShutdown->isChecked()) + return 5; + return(0); +} + +int ButtonsConfig::getPower() +{ + if (!apm) + return(power); + if (powerHibernate && powerHibernate->isChecked()) + return 3; + if (powerStandby && powerStandby->isChecked()) + return 1; + if (powerSuspend && powerSuspend->isChecked()) + return 2; + if (powerLogout && powerLogout->isChecked()) + return 4; + if (powerShutdown && powerShutdown->isChecked()) + return 5; + return(0); +} + +void ButtonsConfig::setPower(int p, int np) +{ + if (!apm) + return; + if (lidSuspend) { + lidSuspend->setChecked(FALSE); + } else { + if (np == 2) np = 0; + } + if (lidShutdown) { + lidShutdown->setChecked(FALSE); + } else { + if (np == 5) np = 0; + } + if (lidLogout) { + lidLogout->setChecked(FALSE); + } else { + if (np == 4) np = 0; + } + if (lidStandby) { + lidStandby->setChecked(FALSE); + } else { + if (np == 1) np = 0; + } + if (lidHibernate) { + lidHibernate->setChecked(FALSE); + } else { + if (np == 3) np = 0; + } + if (lidOff) + lidOff->setChecked(FALSE); + switch (np) { + case 0: if (lidOff) + lidOff->setChecked(TRUE); + break; + case 1: lidStandby->setChecked(TRUE);break; + case 2: lidSuspend->setChecked(TRUE);break; + case 3: lidHibernate->setChecked(TRUE);break; + case 4: lidLogout->setChecked(TRUE);break; + case 5: lidShutdown->setChecked(TRUE);break; + } + if (powerSuspend) { + powerSuspend->setChecked(FALSE); + } else { + if (p == 2) p = 0; + } + if (powerLogout) { + powerLogout->setChecked(FALSE); + } else { + if (p == 4) p = 0; + } + if (powerShutdown) { + powerShutdown->setChecked(FALSE); + } else { + if (p == 5) p = 0; + } + if (powerStandby) { + powerStandby->setChecked(FALSE); + } else { + if (p == 1) p = 0; + } + if (powerHibernate) { + powerHibernate->setChecked(FALSE); + } else { + if (p == 3) p = 0; + } + if (powerOff) + powerOff->setChecked(FALSE); + switch (p) { + case 0: if (powerOff) + powerOff->setChecked(TRUE); + break; + case 1: powerStandby->setChecked(TRUE);break; + case 2: powerSuspend->setChecked(TRUE);break; + case 3: powerHibernate->setChecked(TRUE);break; + case 4: powerLogout->setChecked(TRUE);break; + case 5: powerShutdown->setChecked(TRUE);break; + } +} + + + +void ButtonsConfig::configChanged() +{ + if (powerBrightness) + powerValBrightness->setEnabled(powerBrightness->isChecked()); + if (lidBrightness) + lidValBrightness->setEnabled(lidBrightness->isChecked()); + + if (powerPerformance) + powerValPerformance->setEnabled(powerPerformance->isChecked()); + if (lidPerformance) + lidValPerformance->setEnabled(lidPerformance->isChecked()); + + if (powerThrottle) + powerValThrottle->setEnabled(powerThrottle->isChecked()); + if (lidThrottle) + lidValThrottle->setEnabled(lidThrottle->isChecked()); + + emit changed(true); +} + + +QString ButtonsConfig::quickHelp() const +{ + return i18n("<h1>Laptop Power Control</h1>This module allows you to " + "configure the power switch or lid closure switch on your laptop " + "so they can trigger system actions"); + +} + +#include "buttons.moc" diff --git a/klaptopdaemon/buttons.h b/klaptopdaemon/buttons.h new file mode 100644 index 0000000..5abd088 --- /dev/null +++ b/klaptopdaemon/buttons.h @@ -0,0 +1,92 @@ +/* + * pcmcia.h + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BUTTONSCONFIG_H__ +#define __BUTTONSCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSlider; +class QButtonGroup; +class QRadioButton; +class QSpinBox; +class KConfig; +class QCheckBox; +class KComboBox; + +class ButtonsConfig : public KCModule +{ + Q_OBJECT +public: + ButtonsConfig( QWidget *parent=0, const char* name=0); + ~ButtonsConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + + +private: + + int getPower(); + int getLid(); + void setPower( int, int ); + + QButtonGroup *lidBox; + QRadioButton *lidStandby, *lidSuspend, *lidOff, *lidHibernate, *lidShutdown, *lidLogout; + QCheckBox *lidBrightness; + QSlider *lidValBrightness; + QCheckBox *lidThrottle; + KComboBox *lidValThrottle; + QCheckBox *lidPerformance; + KComboBox *lidValPerformance; + QButtonGroup *powerBox; + QRadioButton *powerStandby, *powerSuspend, *powerOff, *powerHibernate, *powerShutdown, *powerLogout; + QCheckBox *powerBrightness; + QSlider *powerValBrightness; + QCheckBox *powerThrottle; + KComboBox *powerValThrottle; + QCheckBox *powerPerformance; + KComboBox *powerValPerformance; + int power_bright_val, lid_bright_val; + bool lid_bright_enabled, power_bright_enabled; + bool lid_throttle_enabled, power_throttle_enabled; + QString lid_throttle_val, power_throttle_val; + bool lid_performance_enabled, power_performance_enabled; + QString lid_performance_val, power_performance_val; + + KConfig *config; + int power, lid, apm; +}; + +#endif + diff --git a/klaptopdaemon/checkcrc.h b/klaptopdaemon/checkcrc.h new file mode 100644 index 0000000..149f28b --- /dev/null +++ b/klaptopdaemon/checkcrc.h @@ -0,0 +1,53 @@ +/* + * checkcrc.h + * + * Copyright (c) 2003 Paul Campbell <[email protected]> + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CHECKCRC_H_ +#define _CHECKCRC_H_ + + + +#include <zlib.h> +#include <stdio.h> + +static void +checkcrc(const char *name, unsigned long &len_res, unsigned long &crc_res) +{ + unsigned long crc = ::crc32(0L, Z_NULL, 0); + unsigned long len = 0; + + FILE *f = ::fopen(name, "r"); + if (f) { + unsigned char buffer[1024]; + for (;;) { + int l = ::fread(buffer, 1, sizeof(buffer), f); + if (l <= 0) + break; + len += l; + crc = ::crc32(crc, buffer, l); + } + ::fclose(f); + } + crc_res = crc; + len_res = len; +} + +#endif diff --git a/klaptopdaemon/configure.in.bot b/klaptopdaemon/configure.in.bot new file mode 100644 index 0000000..51630ed --- /dev/null +++ b/klaptopdaemon/configure.in.bot @@ -0,0 +1,9 @@ +if test -z "$TPCTL"; then + echo "" + echo "You're missing tpctl. If you're using a ThinkPad, you may miss" + echo "some functionality of klaptopdaemon." + echo "You can get them from http://tpctl.sourceforge.net/tpctlhome.htm" + echo "" + all_tests=bad +fi + diff --git a/klaptopdaemon/configure.in.in b/klaptopdaemon/configure.in.in new file mode 100644 index 0000000..c1c5427 --- /dev/null +++ b/klaptopdaemon/configure.in.in @@ -0,0 +1,49 @@ +KDE_FIND_PATH(tpctl, TPCTL, [$exec_prefix/bin $prefix/bin /usr/bin /usr/local/bin /opt/local/bin], [TPCTL=""]) +AC_DEFINE_UNQUOTED(PATH_TPCTL, "$TPCTL", [Defines the executable of tpctl]) + +AC_CHECK_HEADERS(machine/apm_bios.h) + +if test "x$kde_use_qt_mac" = "xyes"; then + DO_NOT_COMPILE="$DO_NOT_COMPILE klaptopdaemon" +fi + + +xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XSS= + +AC_ARG_WITH([xscreensaver], + AC_HELP_STRING([--without-xscreensaver], [Disable XScreenSaver support (default: check)]) ) + +if test "x$with_xscreensaver" != "xno"; then + KDE_CHECK_HEADER(X11/extensions/scrnsaver.h, + [ + AC_CHECK_LIB(Xext,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXext" + ], + [ + ld_shared_flag= + xss_save_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" + KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"]) + AC_CHECK_LIB(Xss,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXss" + ], + [], + [ $ld_shared_flag $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + CXXFLAGS="$xss_save_cxxflags" + ], + [ $X_PRE_LIBS -lX11 $X_EXTRA_LIBS ]) + ], [], + [ + #include <X11/Xlib.h> + ] ) +fi + +AC_SUBST(LIB_XSS) +LDFLAGS="$xss_save_ldflags" diff --git a/klaptopdaemon/daemon_state.cpp b/klaptopdaemon/daemon_state.cpp new file mode 100644 index 0000000..5ca0d28 --- /dev/null +++ b/klaptopdaemon/daemon_state.cpp @@ -0,0 +1,282 @@ +/* + * daemon_state.cpp + * Copyright (C) 1999, 2003 Paul Campbell <[email protected]> + * + * this replaces kcmlaptop - there are 2 parts - one is the panels that + * put the setup configuration in the "kcmlaptop" configm, the other + * is the laptop_daemon (this guy) who watches the battery state + * and does stuff as a result + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <stdlib.h> +#include <fcntl.h> + +#include <qtimer.h> + +#include <kconfig.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include "daemon_state.h" +#include "portable.h" +#include <kaboutdata.h> +#include <kaudioplayer.h> +#include <sys/ioctl.h> +#include <kmessagebox.h> +#include <dcopclient.h> +#include <qsocketnotifier.h> +#include <qcursor.h> + + +#include <unistd.h> +#include <sys/time.h> + +daemon_state::daemon_state() +{ + exists = laptop_portable::has_power_management(); + has_brightness = laptop_portable::has_brightness(); + QStringList profile_list; + int current_profile; + bool *active_list; + has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + +} + +daemon_state::~daemon_state() +{ +} + +void daemon_state::load() +{ + KConfig *config = new KConfig("kcmlaptoprc"); + + if (config == 0) { + ::fprintf(stderr, "laptop_daemon: can't open kcmlaptop config files\n"); + ::exit(2); + } + + + // acpi settings + config->setGroup("AcpiDefault"); + bool enablestandby = config->readBoolEntry("EnableStandby", false); + bool enablesuspend = config->readBoolEntry("EnableSuspend", false); + bool enablehibernate = config->readBoolEntry("EnableHibernate", false); + bool enableperformance = config->readBoolEntry("EnablePerformance", false); + bool enablethrottle = config->readBoolEntry("EnableThrottle", false); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config->setGroup("ApmDefault"); + enablestandby = config->readBoolEntry("EnableStandby", false); + enablesuspend = config->readBoolEntry("EnableSuspend", false); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + + config->setGroup("SoftwareSuspendDefault"); + enablehibernate = config->readBoolEntry("EnableHibernate", false); + laptop_portable::software_suspend_set_mask(enablehibernate); + + exists = laptop_portable::has_power_management(); + has_brightness = laptop_portable::has_brightness(); + QStringList profile_list; + int current_profile; + bool *active_list; + has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + + bool can_suspend = laptop_portable::has_suspend(); + bool can_hibernate = laptop_portable::has_hibernation(); + bool can_standby = laptop_portable::has_standby(); + + // power control settings + config->setGroup("LaptopPower"); + power_action[0] = config->readNumEntry("PowerSuspend", 0); + switch (power_action[0]) { + case 1: if (!can_standby) power_action[0] = 0; break; + case 2: if (!can_suspend) power_action[0] = 0; break; + case 3: if (!can_hibernate) power_action[0] = 0; break; + } + power_action[1] = config->readNumEntry("NoPowerSuspend", 1); + switch (power_action[1]) { + case 1: if (!can_standby) power_action[1] = 0; break; + case 2: if (!can_suspend) power_action[1] = 0; break; + case 3: if (!can_hibernate) power_action[1] = 0; break; + } + power_brightness_enabled[0] = config->readBoolEntry("PowerBrightnessEnabled", 0)&has_brightness; + power_brightness_enabled[1] = config->readBoolEntry("NoPowerBrightnessEnabled", 0)&has_brightness; + power_brightness[0] = config->readNumEntry("PowerBrightness", 255); + power_brightness[1] = config->readNumEntry("NoPowerBrightness", 0); + power_performance_enabled[0] = config->readBoolEntry("PowerPerformanceEnabled", 0)&has_performance; + power_performance_enabled[1] = config->readBoolEntry("NoPowerPerformanceEnabled", 0)&has_performance; + power_performance[0] = config->readEntry("PowerPerformance", ""); + power_performance[1] = config->readEntry("NoPowerPerformance", ""); + power_throttle_enabled[0] = config->readBoolEntry("PowerThrottleEnabled", 0)&has_throttle; + power_throttle_enabled[1] = config->readBoolEntry("NoPowerThrottleEnabled", 0)&has_throttle; + power_throttle[0] = config->readEntry("PowerThrottle", ""); + power_throttle[1] = config->readEntry("NoPowerThrottle", ""); + power_wait[0] = 60*config->readNumEntry("PowerWait", 20); + power_wait[1] = 60*config->readNumEntry("NoPowerWait", 5); + lav_enabled[0] = config->readBoolEntry("LavEnabled", 0); + lav_enabled[1] = config->readBoolEntry("NoLavEnabled", 0); + lav_val[0] = config->readDoubleNumEntry("PowerLav", -1); + lav_val[1] = config->readDoubleNumEntry("NoPowerLav", -1); + + // General settings + config->setGroup("BatteryDefault"); + poll = config->readNumEntry("Poll", 20); + enabled = config->readBoolEntry("Enable", true)&exists; + notifyMeWhenFull = config->readBoolEntry("NotifyMe", false)&exists; + useBlankSaver = config->readBoolEntry("BlankSaver", false); + noBatteryIcon = config->readEntry("NoBatteryPixmap", "laptop_nobattery"); + noChargeIcon = config->readEntry("NoChargePixmap", "laptop_nocharge"); + chargeIcon = config->readEntry("ChargePixmap", "laptop_charge"); + + + config->setGroup("BatteryLow"); + time_based_action_low = config->readBoolEntry("TimeBasedAction", true); + low[0] = config->readNumEntry("LowValTime", 15); + low[1] = config->readNumEntry("LowValPercent", 7); + runCommand[0] = config->readBoolEntry("RunCommand", false)&exists; + runCommandPath[0] = config->readEntry("RunCommandPath"); + playSound[0] = config->readBoolEntry("PlaySound", false)&exists; + playSoundPath[0] = config->readEntry("PlaySoundPath"); + systemBeep[0] = config->readBoolEntry("SystemBeep", true)&exists; + logout[0] = config->readBoolEntry("Logout", false)&exists; + shutdown[0] = config->readBoolEntry("Shutdown", false)&exists; + notify[0] = config->readBoolEntry("Notify", true)&exists; + do_hibernate[0] = config->readBoolEntry("Hibernate", false)&can_hibernate&exists; + do_suspend[0] = config->readBoolEntry("Suspend", false)&can_suspend&exists; + do_standby[0] = config->readBoolEntry("Standby", false)&can_standby&exists; + do_brightness[0] = config->readBoolEntry("Brightness", false)&has_brightness&exists; + val_brightness[0] = config->readNumEntry("BrightnessValue", 0); + do_performance[0] = config->readBoolEntry("Performance", false)&has_performance&exists; + val_performance[0] = config->readEntry("PerformanceValue", ""); + do_throttle[0] = config->readBoolEntry("Throttle", false)&has_throttle&exists; + val_throttle[0] = config->readEntry("ThrottleValue", ""); + have_time = config->readNumEntry("HaveTime", 2); + + if (!have_time && laptop_portable::has_battery_time()) + have_time = 1; + + config->setGroup("BatteryCritical"); + time_based_action_critical = config->readBoolEntry("TimeBasedAction", true); + low[2] = config->readNumEntry("CriticalValTime", 5); + low[3] = config->readNumEntry("CriticalValPercent", 3); + runCommand[1] = config->readBoolEntry("RunCommand", false)&exists; + runCommandPath[1] = config->readEntry("RunCommandPath"); + playSound[1] = config->readBoolEntry("PlaySound", false)&exists; + playSoundPath[1] = config->readEntry("PlaySoundPath"); + systemBeep[1] = config->readBoolEntry("SystemBeep", true)&exists; + logout[1] = config->readBoolEntry("Logout", false)&exists; + shutdown[1] = config->readBoolEntry("Shutdown", false)&exists; + notify[1] = config->readBoolEntry("Notify", (can_suspend?false:true))&exists; + do_hibernate[1] = config->readBoolEntry("Hibernate", false)&can_hibernate&exists; + do_suspend[1] = config->readBoolEntry("Suspend", (can_suspend?true:false))&can_suspend&exists; + do_standby[1] = config->readBoolEntry("Standby", false)&can_standby&exists; + do_brightness[1] = config->readBoolEntry("Brightness", false)&has_brightness&exists; + val_brightness[1] = config->readNumEntry("BrightnessValue", 0); + do_performance[1] = config->readBoolEntry("Performance", false)&has_performance&exists; + val_performance[1] = config->readEntry("PerformanceValue", ""); + do_throttle[1] = config->readBoolEntry("Throttle", false)&has_throttle&exists; + val_throttle[1] = config->readEntry("ThrottleValue", ""); + + config->setGroup("ProfileDefault"); + bright_pon = config->readBoolEntry("EnableBrightnessOn", false)&has_brightness; + bright_poff = config->readBoolEntry("EnableBrightnessOff", false)&has_brightness; + performance_pon = config->readBoolEntry("EnablePerformanceOn", false)&has_performance; + performance_poff = config->readBoolEntry("EnablePerformanceOff", false)&has_performance; + throttle_pon = config->readBoolEntry("EnableThrottleOn", false)&has_throttle; + throttle_poff = config->readBoolEntry("EnableThrottleOff", false)&has_throttle; + bright_son = config->readNumEntry("BrightnessOnLevel", 255); + bright_soff = config->readNumEntry("BrightnessOffLevel", 160); + performance_val_on = config->readEntry("PerformanceOnLevel", ""); + performance_val_off = config->readEntry("PerformanceOffLevel", ""); + throttle_val_on = config->readEntry("ThrottleOnLevel", ""); + throttle_val_off = config->readEntry("ThrottleOffLevel", ""); + + config->setGroup("LaptopButtons"); + enable_lid_button = laptop_portable::has_button(laptop_portable::LidButton); + enable_power_button = laptop_portable::has_button(laptop_portable::PowerButton); + button_lid = (enable_lid_button?config->readNumEntry("LidSuspend", 0):0); + if (!enable_lid_button) { + button_lid = 0; + } else + switch (button_lid) { + case 1: if (!can_standby) button_lid = 0; break; + case 2: if (!can_suspend) button_lid = 0; break; + case 3: if (!can_hibernate) button_lid = 0; break; + } + button_power = (enable_power_button?config->readNumEntry("PowerSuspend", 0):0); + if (!enable_power_button) { + button_power = 0; + } else + switch (button_power) { + case 1: if (!can_standby) button_power = 0; break; + case 2: if (!can_suspend) button_power = 0; break; + case 3: if (!can_hibernate) button_power = 0; break; + } + button_lid_bright_enabled = config->readBoolEntry("LidBrightnessEnabled", 0)&enable_lid_button&has_brightness; + button_power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0)&enable_power_button&has_brightness; + button_lid_bright_val = config->readNumEntry("LidBrightness", 0); + button_power_bright_val = config->readNumEntry("PowerBrightness", 0); + button_lid_performance_enabled = config->readBoolEntry("LidPerformanceEnabled", 0)&enable_lid_button&has_performance; + button_power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0)&enable_power_button&has_performance; + button_lid_performance_val = config->readEntry("LidPerformance", ""); + button_power_performance_val = config->readEntry("PowerPerformance", ""); + button_lid_throttle_enabled = config->readBoolEntry("LidThrottleEnabled", 0)&enable_lid_button&has_throttle; + button_power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0)&enable_power_button&has_throttle; + button_lid_throttle_val = config->readEntry("LidThrottle", ""); + button_power_throttle_val = config->readEntry("PowerThrottle", ""); + + config->setGroup("SonyDefault"); + sony_enablescrollbar = config->readBoolEntry("EnableScrollBar", false); + sony_middleemulation = config->readBoolEntry("EnableMiddleEmulation", false); + + delete config; +} + +bool +daemon_state::need_to_run() +{ + // + // look for reasons NOT to run the daemon + // + if (!exists) + return(0); + if (!enabled && !notifyMeWhenFull && + !runCommand[0] && !playSound[0] && !systemBeep[0] && !notify[0] && !do_suspend[0] && + !do_standby[0] && !logout[0] && !shutdown[0] && !do_hibernate[0] && + !runCommand[1] && !playSound[1] && !systemBeep[1] && !notify[1] && !do_suspend[1] && + !do_standby[1] && !logout[1] && !shutdown[1] && !do_hibernate[0] && + !sony_enablescrollbar && !sony_middleemulation && !do_brightness[0] && !do_brightness[1] && + button_lid==0 && button_power==0 && !button_lid_bright_enabled && !button_power_bright_enabled && + !button_lid_performance_enabled && !button_power_performance_enabled && !button_lid_throttle_enabled && !button_power_throttle_enabled && + !do_performance[0] && !do_performance[1] && !do_throttle[0] && !do_throttle[1] && + !bright_pon && !bright_poff && !performance_pon && !performance_poff && !throttle_pon && !throttle_poff && + !power_brightness_enabled[0] && !power_brightness_enabled[0] && + !power_performance_enabled[0] && !power_performance_enabled[1] && !power_throttle_enabled[0] && !power_throttle_enabled[1] && + power_action[0] == 0 && power_action[1] == 0) // if no reason to be running quit + return(0); + return(1); +} + diff --git a/klaptopdaemon/daemon_state.h b/klaptopdaemon/daemon_state.h new file mode 100644 index 0000000..6da4e73 --- /dev/null +++ b/klaptopdaemon/daemon_state.h @@ -0,0 +1,141 @@ +#ifndef __DAEMON_STATE_H +#define __DAEMON_STATE_H 1 +/* + * daemon_state.h + * Copyright (C) 1999, 2003 Paul Campbell <[email protected]> + * + * This file contains the saved config state for the laptop daemon + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include <qdir.h> +#include <unistd.h> +#include <time.h> +#include <qmovie.h> +#include <qptrlist.h> +#include <qfileinfo.h> +#include <qimage.h> +#include <kdelibs_export.h> + +class KDE_EXPORT daemon_state +{ +public: + daemon_state(); + ~daemon_state(); + void load(); + bool need_to_run(); + + bool exists; + bool has_brightness; + bool has_performance; + bool has_throttle; + + QString noBatteryIcon; + QString chargeIcon; + QString noChargeIcon; + + // + // power out actions + // + + int power_wait[2]; // how close to the end when we trigger the action + int power_action[2]; // what to do when this action is triggered + int power_brightness[2]; // which brightness level to switch to + bool power_brightness_enabled[2]; // and whether to switch + QString power_performance[2]; // which performance level to switch to + bool power_performance_enabled[2]; // and whether to switch + QString power_throttle[2]; // which throttling level to switch to + bool power_throttle_enabled[2]; // and whether to switch + bool lav_enabled[2]; // check LAV first + float lav_val[2]; // don't act if higher than this + + // + // power out warnings + // + + bool systemBeep[2]; + bool logout[2]; + bool shutdown[2]; + bool runCommand[2]; + QString runCommandPath[2]; + bool playSound[2]; + QString playSoundPath[2]; + bool notify[2]; + bool do_suspend[2]; + bool do_hibernate[2]; + bool do_standby[2]; + bool do_brightness[2]; + int val_brightness[2]; + bool do_performance[2]; + QString val_performance[2]; + bool do_throttle[2]; + QString val_throttle[2]; + bool time_based_action_low, time_based_action_critical; + int low[4]; + int poll; // how often to pol + + + + bool enabled; + bool notifyMeWhenFull; + bool useBlankSaver; + + + int have_time; + + // sony jog-bar support + + bool sony_enablescrollbar; // enable jog bar support + bool sony_middleemulation; // press on jog bar emulates mouse middle button + + // brightness + + bool bright_pon; // auto set brightness when powered + int bright_son; // value to set + bool bright_poff; // auto set brightness when on battery + int bright_soff; // value to set + + // performance + + bool performance_pon, performance_poff; + QString performance_val_on, performance_val_off; + + // throttle + + bool throttle_pon, throttle_poff; + QString throttle_val_on, throttle_val_off; + + // button triggered stuff + int button_lid; + int button_power; + bool button_lid_bright_enabled; + bool button_power_bright_enabled; + int button_lid_bright_val; + int button_power_bright_val; + bool button_lid_performance_enabled; + bool button_power_performance_enabled; + QString button_lid_performance_val; + QString button_power_performance_val; + bool button_lid_throttle_enabled; + bool button_power_throttle_enabled; + QString button_lid_throttle_val; + QString button_power_throttle_val; + bool enable_lid_button; + bool enable_power_button; + +}; +#endif diff --git a/klaptopdaemon/daemondock.cpp b/klaptopdaemon/daemondock.cpp new file mode 100644 index 0000000..3551931 --- /dev/null +++ b/klaptopdaemon/daemondock.cpp @@ -0,0 +1,756 @@ +/* + * daemondock.cpp + * Copyright (C) 1999 Paul Campbell <[email protected]> + * Copyright (C) 2006 Flavio Castelli <[email protected]> + * + * This file contains the docked widget for the laptop battery monitor + * + * $Id$ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <qcursor.h> + +#include <qslider.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <dcopclient.h> +#include <dcopref.h> +#include "kpcmciainfo.h" +#include "daemondock.h" +#include "portable.h" +#include <kiconloader.h> +#include <kapplication.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kconfig.h> +#include <kglobalsettings.h> +#include <kmessagebox.h> +#include <qvbox.h> +#include <qstringlist.h> +#include <qbitmap.h> +#include <qpainter.h> +#include <kiconeffect.h> +extern void wake_laptop_daemon(); + +laptop_dock::laptop_dock( laptop_daemon* parent ) + : KSystemTray() +{ + setCaption(i18n("KLaptop Daemon")); + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + _pcmcia = NULL; + pdaemon = parent; + current_code = -1; + brightness_widget = 0; + instance = new KInstance("klaptopdaemon"); + // popup menu for right mouse button + rightPopup = contextMenu(); + SetupPopup(); +} + +void +laptop_dock::SetupPopup() +{ + rightPopup->clear(); + rightPopup->insertTitle(SmallIcon("laptop_battery"), "KLaptop", 999); // otherwise we look like KDED + + int has_brightness = laptop_portable::has_brightness(); + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + QStringList profile_list; + int current_profile; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + rightPopup->insertItem(SmallIcon("configure"), i18n("&Configure KLaptop..."), this, SLOT(invokeSetup())); + + if (has_brightness) + rightPopup->insertItem(i18n("Screen Brightness..."), this, SLOT(invokeBrightness())); + if (has_performance) { + performance_popup = new QPopupMenu(0, "performance"); + performance_popup->setCheckable(1); + rightPopup->insertItem(i18n("Performance Profile..."), performance_popup); + connect( performance_popup, SIGNAL( activated( int ) ), this, SLOT( activate_performance( int ) ) ); + connect( performance_popup, SIGNAL( aboutToShow() ), this, SLOT( fill_performance() ) ); + } else { + performance_popup = 0; + } + if (has_throttle) { + throttle_popup = new QPopupMenu(0, "throttle"); + throttle_popup->setCheckable(1); + rightPopup->insertItem(i18n("CPU Throttling..."), throttle_popup); + connect( throttle_popup, SIGNAL( activated( int ) ), this, SLOT( activate_throttle( int ) ) ); + connect( throttle_popup, SIGNAL( aboutToShow() ), this, SLOT( fill_throttle() ) ); + } else { + throttle_popup = 0; + } + + if (can_standby || can_suspend || can_hibernate) { + rightPopup->insertSeparator(); + if (can_standby) rightPopup->insertItem(i18n("Standby..."), this, SLOT(invokeStandby())); + if (can_suspend) rightPopup->insertItem(i18n("&Lock && Suspend..."), this, SLOT(invokeLockSuspend())); + if (can_suspend) rightPopup->insertItem(i18n("&Suspend..."), this, SLOT(invokeSuspend())); + if (can_hibernate) rightPopup->insertItem(i18n("&Lock && Hibernate..."), this, SLOT(invokeLockHibernation())); + if (can_hibernate) rightPopup->insertItem(i18n("&Hibernate..."), this, SLOT(invokeHibernation())); + } + + rightPopup->insertSeparator(); + rightPopup->insertItem(i18n("&Hide Monitor"), this, SLOT(slotHide())); + rightPopup->insertItem(SmallIcon("exit"), KStdGuiItem::quit().text(), this, SLOT(slotQuit())); +} + +laptop_dock::~laptop_dock() +{ + delete instance; + if (brightness_widget) + delete brightness_widget; + if (throttle_popup) + delete throttle_popup; + if (performance_popup) + delete performance_popup; +} + +void +laptop_dock::activate_throttle(int ind) +{ + pdaemon->SetThrottle(throttle_popup->text(ind)); +} + +void +laptop_dock::fill_throttle() +{ + throttle_popup->clear(); + int current; + QStringList list; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(1, current, list, active_list); + if (!has_throttle && !list.empty()) + return; + int n=0; + for (QValueListIterator<QString> i = list.begin();i != list.end();i++) { + throttle_popup->insertItem(*i, n); + throttle_popup->setItemEnabled(n, active_list[n]); + n++; + } + throttle_popup->setItemChecked(current, 1); +} + +void +laptop_dock::activate_performance(int ind) +{ + pdaemon->SetPerformance(performance_popup->text(ind)); +} + +void +laptop_dock::fill_performance() +{ + performance_popup->clear(); + int current; + QStringList list; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(1, current, list, active_list); + if (!has_performance && !list.empty()) + return; + int n=0; + for (QValueListIterator<QString> i = list.begin();i != list.end();i++) { + performance_popup->insertItem(*i, n); + performance_popup->setItemEnabled(n, active_list[n]); + n++; + } + performance_popup->setItemChecked(current, 1); +} + +void +laptop_dock::invokeBrightnessSlider(int v) +{ + v=255-v; + pdaemon->SetBrightness(0, v); + brightness = v; +} + +void +laptop_dock::invokeBrightness() +{ + brightness = pdaemon->GetBrightness(); + + if (brightness < 0) + brightness = 255; + + if (brightness_widget == 0) { + brightness_widget = new QVBox(0L, "Brightness", WStyle_Customize | WType_Popup); + brightness_widget->setFrameStyle(QFrame::PopupPanel); + brightness_widget->setMargin(KDialog::marginHint()); + brightness_slider = new QSlider(0, 255, 16, 255-brightness, Qt::Vertical, brightness_widget, 0); + brightness_slider->setMinimumHeight(40); + brightness_slider->setMinimumWidth(15); + connect(brightness_slider, SIGNAL(valueChanged(int)), this, SLOT(invokeBrightnessSlider(int))); + brightness_widget->resize(brightness_widget->sizeHint()); + } else { + brightness_slider->setValue(255-brightness); + } + if (!brightness_widget->isVisible()) { + QRect desktop = KGlobalSettings::desktopGeometry(this); + int sw = desktop.width(); + int sh = desktop.height(); + int sx = desktop.x(); + int sy = desktop.y(); + QPoint pos = QCursor::pos(); + int x = pos.x(); + int y = pos.y(); + y -= brightness_widget->geometry().height(); + int w = brightness_widget->width(); + int h = brightness_widget->height(); + if (x+w > sw) + x = pos.x()-w; + if (y+h > sh) + y = pos.y()-h; + if (x < sx) + x = pos.x(); + if (y < sy) + y = pos.y(); + brightness_widget->move(x, y); + brightness_widget->show(); + } +} + +void laptop_dock::slotGoRoot(int /*id*/) { +#ifdef NOTDEF + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow KLaptopDaemon to restart " + "itself as the superuser. It may take " + "up to a minute for the new daemon to " + "start up and the old one to close."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + "switchToPCMCIAPrompt"); + if (rc == KMessageBox::Continue) { + KProcess *_rootProcess; + _rootProcess = new KProcess; + *_rootProcess << kdesu; + *_rootProcess << "-u"; + *_rootProcess << "root"; + //*_rootProcess << "--nonewdcop"; + *_rootProcess << KStandardDirs::findExe("klaptopdaemon"); + connect(_rootProcess, SIGNAL(processExited(KProcess*)), + this, SLOT(rootExited(KProcess*))); + _rootProcess->start(KProcess::NotifyOnExit); + // We should disable this menu item here now. + } + } else { + KMessageBox::sorry(0, i18n("PCMCIA cannot be enabled since kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } +#else + KMessageBox::sorry(0, i18n("PCMCIA cannot be enabled just now."), + i18n("KLaptopDaemon")); +#endif +} + + +void laptop_dock::slotHide() { + int confirm = KMessageBox::questionYesNo(0, i18n("Are you sure you want to hide the battery monitor? Your battery will still be monitored in the background."), QString::null, i18n("Hide Monitor"), i18n("Do Not Hide"), "hideConfirm"); + + if (confirm != KMessageBox::Yes) + return; + + // just tell ourselves to hide the battery + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryDefault"); + config->writeEntry("Enable", false); + config->sync(); + delete config; + } + wake_laptop_daemon(); +} + + +void laptop_dock::slotQuit() { + int confirm = KMessageBox::questionYesNo(0, i18n("Are you sure you want to quit the battery monitor?"), QString::null, KStdGuiItem::quit(), KStdGuiItem::cancel(), "quitConfirm"); + + if (confirm != KMessageBox::Yes) + return; + + confirm = KMessageBox::questionYesNo(0, i18n("Do you wish to disable the battery monitor from starting in the future?"), QString::null, i18n("Disable"), i18n("Keep Enabled"), "restartMonitor"); + + if (confirm == KMessageBox::Yes) { + // just tell ourselves to hide the battery + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryDefault"); + config->writeEntry("Enable", false); + config->sync(); + delete config; + } + } + pdaemon->quit(); +} + + +void laptop_dock::rootExited(KProcess *p) { + if (p && p->isRunning()) { + p->detach(); + } + exit(0); +} + + +void laptop_dock::slotEjectAction(int id) { +KPCMCIACard *f = NULL; + f = _ejectActions[id]; + + if (f) f->eject(); +} + + +void laptop_dock::slotSuspendAction(int id) { +KPCMCIACard *f = NULL; + f = _suspendActions[id]; + + if (f) f->suspend(); +} + + +void laptop_dock::slotResumeAction(int id) { +KPCMCIACard *f = NULL; + f = _resumeActions[id]; + + if (f) f->resume(); +} + + +void laptop_dock::slotResetAction(int id) { +KPCMCIACard *f = NULL; + f = _resetActions[id]; + + if (f) f->reset(); +} + + +void laptop_dock::slotInsertAction(int id) { +KPCMCIACard *f = NULL; + f = _insertActions[id]; + + if (f) f->insert(); +} + + +void laptop_dock::slotDisplayAction(int id) { +KPCMCIAInfo *f = new KPCMCIAInfo(_pcmcia); + f->showTab(_displayActions[id]->num()); +} + +void laptop_dock::mousePressEvent( QMouseEvent *event ) +{ + if(event->button() == LeftButton) { + QPopupMenu *popup = new QPopupMenu(0, "popup"); + + if (!pdaemon->exists()) { + popup->insertItem(i18n("Power Manager Not Found")); + } else { + QString tmp; + + if (pdaemon->val >= 0) { + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("%1:%2 hours left").arg(pdaemon->left/60).arg(num3); + } else { + // no remaining time available + tmp = i18n("%1% charged").arg(pdaemon->val); + } + } else { + tmp = i18n("No Battery"); + } + popup->insertItem(tmp); + popup->setItemEnabled(0, 0); + popup->insertSeparator(); + if (pdaemon->powered && pdaemon->val >= 0) { + popup->insertItem(i18n("Charging")); + } else { + popup->insertItem(i18n("Not Charging")); + } + popup->setItemEnabled(1, 0); + } + + /** + * CPU Frequency scaling support + * - show the cpu profile and current frequency + */ + if (laptop_portable::has_cpufreq()) { + QString speed = laptop_portable::cpu_frequency(); + if (!speed.isEmpty()) { + popup->insertSeparator(); + popup->insertItem(i18n("CPU: %1").arg(speed)); + } + } + + /** + * ADD the PCMCIA entries here + */ + if (_pcmcia && _pcmcia->haveCardServices()) { + QString slotname = i18n("Slot %1"); // up here so we only construct it once + int id; + popup->insertSeparator(); + _ejectActions.clear(); + _resetActions.clear(); + _insertActions.clear(); + _suspendActions.clear(); + _resumeActions.clear(); + _displayActions.clear(); + id = popup->insertItem(i18n("Card Slots..."), this, SLOT(slotDisplayAction(int))); + _displayActions.insert(id, _pcmcia->getCard(0)); + for (int i = 0; i < _pcmcia->getCardCount(); i++) { + KPCMCIACard *thiscard; + thiscard = _pcmcia->getCard(i); + if (thiscard && (thiscard->present())) { + QPopupMenu *thisSub = new QPopupMenu(popup, thiscard->name().latin1()); + id = thisSub->insertItem(i18n("Details..."), this, SLOT(slotDisplayAction(int))); + _displayActions.insert(id, thiscard); + + // add the actions + QPopupMenu *actionsSub = new QPopupMenu(thisSub, "actions"); + id = actionsSub->insertItem(i18n("Eject"), this, SLOT(slotEjectAction(int))); + actionsSub->setItemEnabled(id, !(thiscard->status() & CARD_STATUS_BUSY)); + _ejectActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Suspend"), this, SLOT(slotSuspendAction(int))); + actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_SUSPEND|CARD_STATUS_BUSY))); + _suspendActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Resume"), this, SLOT(slotResumeAction(int))); + actionsSub->setItemEnabled(id, (thiscard->status() & CARD_STATUS_SUSPEND)); + _resumeActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Reset"), this, SLOT(slotResetAction(int))); + _resetActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Insert"), this, SLOT(slotInsertAction(int))); + _insertActions.insert(id, thiscard); + actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))); + thisSub->insertItem(i18n("Actions"), actionsSub); + + // add a few bits of information + thisSub->insertSeparator(); + thisSub->insertItem(slotname.arg(thiscard->num()+1)); + if (thiscard->status() & CARD_STATUS_READY) + thisSub->insertItem(i18n("Ready")); + if (thiscard->status() & CARD_STATUS_BUSY) + thisSub->insertItem(i18n("Busy")); + if (thiscard->status() & CARD_STATUS_SUSPEND) + thisSub->insertItem(i18n("Suspended")); + popup->insertItem(thiscard->name(), thisSub); + } + } + } else if (_pcmcia && geteuid() != 0) { + popup->insertItem(i18n("Enable PCMCIA")); + } + + popup->popup(QCursor::pos()); + } + +} +void laptop_dock::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( !rect().contains( e->pos() ) ) + return; + + switch ( e->button() ) { + case LeftButton: + break; + case MidButton: + // fall through + case RightButton: + { + KPopupMenu *menu = contextMenu(); + contextMenuAboutToShow( menu ); + menu->popup( e->globalPos() ); + } + break; + default: + // nothing + break; + } +} +void laptop_dock::showEvent( QShowEvent * ) +{ + +} +void laptop_dock::invokeHibernation() +{ + laptop_portable::invoke_hibernation(); +} + +void laptop_dock::invokeLockHibernation() +{ + DCOPRef dr("kdesktop", "KScreensaverIface"); + DCOPReply reply=dr.call("lock"); + + laptop_portable::invoke_hibernation(); +} +void laptop_dock::invokeStandby() +{ + laptop_portable::invoke_standby(); +} + +void laptop_dock::invokeSuspend() +{ + laptop_portable::invoke_suspend(); +} + +void laptop_dock::invokeLockSuspend() +{ + DCOPClient* client = kapp->dcopClient(); + if (client) + client->send("kdesktop", "KScreensaverIface", "lock()", ""); + laptop_portable::invoke_suspend(); +} + +void laptop_dock::invokeSetup() +{ + KProcess proc; + proc << KStandardDirs::findExe("kcmshell"); + proc << "laptop"; + proc.start(KProcess::DontCare); + proc.detach(); +} + +void +laptop_dock::reload_icon() +{ + // we will try to deduce the pixmap (or gif) name now. it will + // vary depending on the dock and power + QString pixmap_name; + + if (!pdaemon->exists()) + pixmap_name = pdaemon->noBatteryIcon(); + else if (!pdaemon->powered) + pixmap_name = pdaemon->noChargeIcon(); + else + pixmap_name = pdaemon->chargeIcon(); + + pm = loadIcon( pixmap_name, instance ); +} + +void laptop_dock::displayPixmap() +{ + int new_code; + + if (!pdaemon->exists()) + new_code = 1; + else if (!pdaemon->powered) + new_code = 2; + else + new_code = 3; + + if (current_code != new_code) { + current_code = new_code; + reload_icon(); + } + + // at this point, we have the file to display. so display it + + QImage image = pm.convertToImage(); + const QBitmap *bmmask = pm.mask(); + QImage mask; + if (bmmask) + mask = bmmask->convertToImage(); + + int w = image.width(); + int h = image.height(); + int count = 0; + QRgb rgb; + int x, y; + for (x = 0; x < w; x++) + for (y = 0; y < h; y++) + if (!bmmask || mask.pixelIndex(x, y) != 0){ + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) + count++; + } + int c = (count*pdaemon->val)/100; + if (pdaemon->val == 100) { + c = count; + } else + if (pdaemon->val != 100 && c == count) + c = count-1; + + + if (c) { + uint ui; + QRgb blue = qRgb(0x00,0x00,0xff); + + if (image.depth() <= 8) { + ui = image.numColors(); // this fix thanks to Sven Krumpke + image.setNumColors(ui+1); + image.setColor(ui, blue); + } else { + ui = 0xff000000|blue; + } + + for (y = h-1; y >= 0; y--) + for (x = 0; x < w; x++) + if (!bmmask || mask.pixelIndex(x, y) != 0){ + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) { + image.setPixel(x, y, ui); + c--; + if (c <= 0) + goto quit; + } + } + } +quit: + + QString tmp; + QString levelString; + + if (!pdaemon->exists()) { + tmp = i18n("Laptop power management not available"); + levelString = i18n("N/A"); + } else + if (pdaemon->powered) { + if (pdaemon->val == 100) { + tmp = i18n("Plugged in - fully charged");; + levelString = "100%"; + } else if (pdaemon->val >= 0) { + levelString.sprintf ("%i%%", pdaemon->val); + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("Plugged in - %1% charged (%2:%3 hours left)") + .arg(pdaemon->val).arg(pdaemon->left/60).arg(num3); + } else { + // no remaining time available + tmp = i18n("Plugged in - %1% charged").arg(pdaemon->val); + } + } else { + tmp = i18n("Plugged in - no battery"); + levelString = i18n("N/A"); + } + } else { + if (pdaemon->val >= 0) { + levelString.sprintf ("%i%%", pdaemon->val); + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("Running on batteries - %1% charged (%2:%3 hours left)") + .arg(pdaemon->val).arg(pdaemon->left/60).arg(num3); + } else { + tmp = i18n("Running on batteries - %1% charged").arg(pdaemon->val); + } + } else { + // running without any power source... + // happens eg. due to ACPI not being able to handle battery hot-plugin + tmp = i18n("No power source found"); + levelString = i18n("N/A"); + } + } + + + // prepare icon for systemtray + + KConfig* config = new KConfig("kcmlaptoprc"); + bool showlevel = false; + + if (config) + { + config->setGroup("BatteryDefault"); + showlevel= config->readBoolEntry("ShowLevel", false); + delete config; + } + + if (showlevel) + { + // lot of code taken from kmail kmsystemtray class + + int oldPixmapWidth = image.size().width(); + int oldPixmapHeight = image.size().height(); + + QFont percentageFont = KGlobalSettings::generalFont(); + percentageFont.setBold(true); + + // decrease the size of the font for the number of unread messages if the + // number doesn't fit into the available space + float percentageFontSize = percentageFont.pointSizeFloat(); + QFontMetrics qfm( percentageFont ); + int width = qfm.width( levelString ); + if( width > oldPixmapWidth ) + { + percentageFontSize *= float( oldPixmapWidth ) / float( width ); + percentageFont.setPointSizeFloat( percentageFontSize ); + } + + // Create an image which represents the number of unread messages + // and which has a transparent background. + // Unfortunately this required the following twisted code because for some + // reason text that is drawn on a transparent pixmap is invisible + // (apparently the alpha channel isn't changed when the text is drawn). + // Therefore I have to draw the text on a solid background and then remove + // the background by making it transparent with QPixmap::setMask. This + // involves the slow createHeuristicMask() function (from the API docs: + // "This function is slow because it involves transformation to a QImage, + // non-trivial computations and a transformation back to a QBitmap."). Then + // I have to convert the resulting QPixmap to a QImage in order to overlay + // the light KMail icon with the number (because KIconEffect::overlay only + // works with QImage). Finally the resulting QImage has to be converted + // back to a QPixmap. + // That's a lot of work for overlaying the KMail icon with the number of + // unread messages, but every other approach I tried failed miserably. + // IK, 2003-09-22 + QPixmap percentagePixmap( oldPixmapWidth, oldPixmapHeight ); + percentagePixmap.fill( Qt::white ); + QPainter p( &percentagePixmap ); + p.setFont( percentageFont ); + p.setPen( Qt::black ); + p.drawText( percentagePixmap.rect(), Qt::AlignCenter, levelString ); + percentagePixmap.setMask( percentagePixmap.createHeuristicMask() ); + QImage percentageImage = percentagePixmap.convertToImage(); + + // Overlay the light KMail icon with the number image + QImage iconWithPercentageImage = image.copy(); + KIconEffect::overlay( iconWithPercentageImage, percentageImage ); + + QPixmap iconWithPercentage; + iconWithPercentage.convertFromImage( iconWithPercentageImage ); + + setPixmap( iconWithPercentage ); + } + else + { + QPixmap q; + q.convertFromImage(image); + if (bmmask) + q.setMask(*bmmask); + setPixmap(q); + } + adjustSize(); + + QToolTip::add(this, tmp); +} + +#include "daemondock.moc" + diff --git a/klaptopdaemon/daemondock.h b/klaptopdaemon/daemondock.h new file mode 100644 index 0000000..7577ffd --- /dev/null +++ b/klaptopdaemon/daemondock.h @@ -0,0 +1,108 @@ +#ifndef DAEMONDOCK +#define DAEMONDOCK 1 +/* + * daemondock.h + * Copyright (C) 1999 Paul Campbell <[email protected]> + * Copyright (C) 2006 Flavio Castelli <[email protected]> + * + * This file contains the docked widget for the laptop battery monitor + * + * $Id$ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "laptop_daemon.h" +#include <ksystemtray.h> + +class laptop_daemon; +class KPCMCIA; +class KPCMCIACard; +class QPopupMenu; +class QVBox; +class QSlider; +class KPopupMenu; + +#include <qmap.h> + +class laptop_dock : public KSystemTray { + + Q_OBJECT + +public: + laptop_dock(laptop_daemon* parent); + ~laptop_dock(); + void displayPixmap(); + + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void showEvent( QShowEvent * ); + void reload_icon(); + + inline void setPCMCIA(KPCMCIA *p) { _pcmcia = p; } + + void SetupPopup(); + +private slots: + void invokeStandby(); + void invokeSuspend(); + void invokeLockSuspend(); + void invokeHibernation(); + void invokeLockHibernation(); + void invokeSetup(); + void invokeBrightness(); + void invokeBrightnessSlider(int v); + + void slotEjectAction(int id); + void slotResumeAction(int id); + void slotSuspendAction(int id); + void slotInsertAction(int id); + void slotResetAction(int id); + void slotDisplayAction(int id); + + void activate_throttle(int ind); + void fill_throttle(); + void activate_performance(int ind); + void fill_performance(); + + + void rootExited(KProcess *p); + void slotGoRoot(int id); + void slotQuit(); + void slotHide(); + +private: + int brightness; + QVBox *brightness_widget; + QSlider *brightness_slider; + laptop_daemon *pdaemon; + QPixmap pm; + QPopupMenu *performance_popup, *throttle_popup; + int current_code; + KPCMCIA *_pcmcia; + QMap<int,KPCMCIACard *> _ejectActions, + _suspendActions, + _resumeActions, + _resetActions, + _displayActions, + _insertActions; + + KInstance *instance; // handle so we get our pretty icons right + KPopupMenu *rightPopup; + +}; +#endif + diff --git a/klaptopdaemon/kpcmcia.cpp b/klaptopdaemon/kpcmcia.cpp new file mode 100644 index 0000000..9dec605 --- /dev/null +++ b/klaptopdaemon/kpcmcia.cpp @@ -0,0 +1,547 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* + * Much of the linux code was migrated from: + * kardinfo Copyright 1999, Mirko Sucker <[email protected]> + */ + +#include <qtimer.h> +#include <qfile.h> +#include <qregexp.h> + +#include <klocale.h> +#include <kinstance.h> +#include <kstandarddirs.h> + + +#include "kpcmcia.h" + + +#ifdef __linux__ + extern "C" { + #include <sys/types.h> + #include <unistd.h> + #include <fcntl.h> + #include <sys/stat.h> + #include <sys/ioctl.h> + #include <sys/file.h> + #include <sys/time.h> + #include "linux/version.h" + #include "linux/cs_types.h" + #include "linux/cs.h" + #include "linux/cistpl.h" + #include "linux/ds.h" + } + +// Taken from cardinfo.c +typedef struct event_tag_t { + event_t event; + const char *name; +} event_tag_t; + + +static event_tag_t event_tag[] = { + { CS_EVENT_CARD_INSERTION, "card insertion" }, + { CS_EVENT_CARD_REMOVAL, "card removal" }, + { CS_EVENT_RESET_PHYSICAL, "prepare for reset" }, + { CS_EVENT_CARD_RESET, "card reset successful" }, + { CS_EVENT_RESET_COMPLETE, "reset request complete" }, + { CS_EVENT_EJECTION_REQUEST, "user eject request" }, + { CS_EVENT_INSERTION_REQUEST, "user insert request" }, + { CS_EVENT_PM_SUSPEND, "suspend card" }, + { CS_EVENT_PM_RESUME, "resume card" }, + { CS_EVENT_REQUEST_ATTENTION, "request attention" } +}; + +#define NTAGS (sizeof(event_tag)/sizeof(event_tag_t)) + +static int lookupDevice(const char *x); +static int openDevice(dev_t dev); + +#else +#include <unistd.h> +#endif + + + +KPCMCIACard::KPCMCIACard() { + _fd = -1; + _num = 9999999; + _status = 0; + _last = 0; + _interrupt = -1; + _ports = ""; + _device = ""; + _module = ""; + _type = ""; + _iotype = 0; + _cardname = i18n("Empty slot."); + _vcc = _vpp = _vpp2 = 0; + _inttype = 0; + _cfgbase = 0; +} + + +KPCMCIACard::~KPCMCIACard() { + if (_fd != -1) close(_fd); +} + + + +// RETURN: <0 => error +// =0 => no error, no update +// >0 => no error, update happened +// +int KPCMCIACard::refresh() { +////////////////////////////////////////////// +///////////// LINUX ONLY +/////////////////////////////////////////////// +#ifdef __linux__ +struct timeval tv; +cs_status_t status; +fd_set rfds; +int rc; +event_t event; +struct stat sb; +config_info_t cfg; +KPCMCIACard oldValues(*this); +int updated = 0; +oldValues._fd = -1; + +#define CHECK_CHANGED(x, y) do { if (x.y != y) updated = 1; } while(0) + + /** + * Get any events on the pcmcia device + */ +tv.tv_sec = 0; tv.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(_fd, &rfds); + rc = select(_fd+1, &rfds, NULL, NULL, &tv); + if (rc > 0) { + rc = read(_fd, (void *)&event, 4); + if (rc == 4) { + int thisEvent = -1; // thisEvent is the index of event in event_tag + for (unsigned int j = 0; j < NTAGS; j++) { + if (event_tag[j].event == event) { + thisEvent = j; + break; + } + if (thisEvent < 0) return -1; + } + } else { + return -1; + } + } else return updated; + + if (event == CS_EVENT_EJECTION_REQUEST) { + _interrupt = -1; + _ports = ""; + _device = ""; + _module = ""; + _type = ""; + _iotype = 0; + _inttype = 0; + _cfgbase = 0; + _cardname = i18n("Empty slot."); + _vcc = _vpp = _vpp2 = 0; + return updated; + } + + /** + * Read in the stab file. + */ + if (!stat(_stabPath.latin1(), &sb) && sb.st_mtime >= _last) { + QFile f(_stabPath.latin1()); + + if (f.open(IO_ReadOnly)) { + QTextStream ts(&f); + bool foundit = false; + QString _thisreg = "^Socket %1: "; + QRegExp thisreg ( _thisreg.arg(_num) ); + + if (flock(f.handle(), LOCK_SH)) return updated; + + _last = sb.st_mtime; + + // find the card + while(!foundit) { + QString s; + if (ts.eof()) break; + s = ts.readLine(); + if (s.contains(thisreg)) { + _cardname = s.right(s.length() - s.find(':') - 1); + _cardname = _cardname.stripWhiteSpace(); + foundit = true; + CHECK_CHANGED(oldValues, _cardname); + } + } + + // read it in + if (foundit && !ts.eof()) { // FIXME: ts.eof() is a bad error!! + QString s = ts.readLine(); + int end; + s.simplifyWhiteSpace(); + + end = s.find(QRegExp("[ \r\t\n]")); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _type = s; + _type.truncate(end); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _module = s; + _module.truncate(end); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _device = s; + _device.truncate(end); + s = s.remove(0, end+1); + CHECK_CHANGED(oldValues, _type); + CHECK_CHANGED(oldValues, _module); + CHECK_CHANGED(oldValues, _device); + } + + flock(f.handle(), LOCK_UN); + f.close(); + } else return -1; + } else return updated; + + + /** + * Get the card's status and configuration information + */ + status.Function = 0; + ioctl(_fd, DS_GET_STATUS, &status); + memset(&cfg, 0, sizeof(cfg)); + ioctl(_fd, DS_GET_CONFIGURATION_INFO, &cfg); + // status is looked up in the table at the top + if (cfg.Attributes & CONF_VALID_CLIENT) { + if (cfg.AssignedIRQ == 0) + _interrupt = -1; + else _interrupt = cfg.AssignedIRQ; + + if (cfg.NumPorts1 > 0) { + int stop = cfg.BasePort1 + cfg.NumPorts1; + if (cfg.NumPorts2 > 0) { + if (stop == cfg.BasePort2) { + _ports.sprintf("%#x-%#x", cfg.BasePort1, stop+cfg.NumPorts2-1); + } else { + _ports.sprintf("%#x-%#x, %#x-%#x", cfg.BasePort1, stop-1, + cfg.BasePort2, cfg.BasePort2+cfg.NumPorts2-1); + } + } else { + _ports.sprintf("%#x-%#x", cfg.BasePort1, stop-1); + } + } + CHECK_CHANGED(oldValues, _ports); + CHECK_CHANGED(oldValues, _interrupt); + } + + _vcc = cfg.Vcc; + _vpp = cfg.Vpp1; + _vpp2 = cfg.Vpp2; + CHECK_CHANGED(oldValues, _vcc); + CHECK_CHANGED(oldValues, _vpp); + CHECK_CHANGED(oldValues, _vpp2); + _inttype = cfg.IntType; + CHECK_CHANGED(oldValues, _inttype); + _iotype = cfg.IOAddrLines; + CHECK_CHANGED(oldValues, _iotype); + _cfgbase = cfg.ConfigBase; + CHECK_CHANGED(oldValues, _cfgbase); + + if (status.CardState & CS_EVENT_CARD_DETECT) + _status |= CARD_STATUS_PRESENT; + if (status.CardState & CS_EVENT_CARD_REMOVAL) + _status &= ~CARD_STATUS_PRESENT; + if (event & CS_EVENT_CARD_REMOVAL) + _status &= ~CARD_STATUS_PRESENT; + + if (!(status.CardState & CS_EVENT_PM_SUSPEND)) { + if (status.CardState & CS_EVENT_READY_CHANGE) { + _status |= CARD_STATUS_READY; + _status &= ~(CARD_STATUS_BUSY|CARD_STATUS_SUSPEND); + } else { + _status |= CARD_STATUS_BUSY; + _status &= ~(CARD_STATUS_READY|CARD_STATUS_SUSPEND); + } + } else if (status.CardState & CS_EVENT_PM_SUSPEND) { + _status |= CARD_STATUS_SUSPEND; + _status &= ~(CARD_STATUS_READY|CARD_STATUS_BUSY); + } + + CHECK_CHANGED(oldValues, _status); + +return updated; +#else +return 0; +#endif +} + + +int KPCMCIACard::insert() { +#ifdef __linux__ + ioctl(_fd, DS_INSERT_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::eject() { +#ifdef __linux__ + ioctl(_fd, DS_EJECT_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::reset() { +#ifdef __linux__ + ioctl(_fd, DS_RESET_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::suspend() { +#ifdef __linux__ + ioctl(_fd, DS_SUSPEND_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::resume() { +#ifdef __linux__ + ioctl(_fd, DS_RESUME_CARD); + return 0; +#else + return -1; +#endif +} + + + + + +KPCMCIA::KPCMCIA(int maxSlots, const char *stabpath) : _maxSlots(maxSlots), + _stabPath(stabpath) { + +_refreshSpeed = 750; + +_haveCardServices = false; +_timer = new QTimer(this); +connect(_timer, SIGNAL(timeout()), this, SLOT(updateCardInfo())); +_cards = new QMemArray<KPCMCIACard *>(_maxSlots+1); +_cardCnt = 0; + + +/////////////////////////////////////////////////// +// LINUX code +/////////////////////////////////////////////////// +#ifdef __linux__ +servinfo_t serv; + + int device = lookupDevice("pcmcia"); + + if (device >= 0) { + for (int z = 0; z < _maxSlots; z++) { + int fd = openDevice((device << 8) + z); + if (fd < 0) break; + (*_cards)[_cardCnt] = new KPCMCIACard; + (*_cards)[_cardCnt]->_stabPath = _stabPath; + (*_cards)[_cardCnt]->_fd = fd; + (*_cards)[_cardCnt]->_num = _cardCnt; + //(*_cards)[_cardCnt]->refresh(); + _cardCnt++; + //kdDebug() << "Found a pcmcia slot" << endl; + } + + if (_cardCnt > 0) { + if (ioctl((*_cards)[0]->_fd, DS_GET_CARD_SERVICES_INFO, &serv) == 0) { + // FIXME: what to do here? + } + _haveCardServices = true; + } + } + + + +_timer->start(_refreshSpeed, true); + +/////////////////////////////////////////////////// +// No supported platform. +/////////////////////////////////////////////////// +#else + +#endif +} + + + + + + + + +KPCMCIA::~KPCMCIA() { +/////////////////////////////////////////////////// +// LINUX code +/////////////////////////////////////////////////// +#ifdef __linux__ + + +/////////////////////////////////////////////////// +// No supported platform. +/////////////////////////////////////////////////// +#else + +#endif + + +delete _timer; +delete _cards; +} + + + + + + + +KPCMCIACard* KPCMCIA::getCard(int num) { + if (num >= _cardCnt || num < 0) return NULL; + return (*_cards)[num]; +} + + + + +void KPCMCIA::updateCardInfo() { + for (int i = 0; i < _cardCnt; i++) { + int rc = (*_cards)[i]->refresh(); + /* + kdDebug() << "CARD UPDATED: " << i << endl + << " Name: " << (*_cards)[i]->_cardname << endl + << " Device: " << (*_cards)[i]->_device << endl + << " VCC: " << (*_cards)[i]->_vcc << endl + << " VPP: " << (*_cards)[i]->_vpp << endl + << " IRQ: " << (*_cards)[i]->_interrupt << endl + << " Ports: " << (*_cards)[i]->_ports << endl + << " Type: " << (*_cards)[i]->_type << endl + << " Module: " << (*_cards)[i]->_module << endl + << endl; + */ + if (rc > 0) emit cardUpdated(i); + } +_timer->start(_refreshSpeed, true); +} + + + +void KPCMCIA::setRefreshSpeed(int msec) { + _refreshSpeed = msec; +} + + +int KPCMCIA::getCardCount() { + return _cardCnt; +} + + +bool KPCMCIA::haveCardServices() { + return _haveCardServices; +} + + +#include "kpcmcia.moc" + + + +#ifdef __linux__ +static int lookupDevice(const char *x) { +QFile df("/proc/devices"); +QString thisreg; + + thisreg = "^[0-9]+ %1$"; + thisreg = thisreg.arg(x); + + if (df.open(IO_ReadOnly)) { + QTextStream t(&df); + QString s; + while (!t.eof()) { + s = t.readLine(); + + if (s.contains(QRegExp(thisreg))) { + int n = (s.left(3).stripWhiteSpace()).toInt(); + df.close(); + return n; + } + } + df.close(); + } +return -1; +} + +static int openDevice(dev_t dev) { +QString tmp_path = locateLocal("tmp", KGlobal::instance()->instanceName()); +QString ext = "_socket%1"; + + tmp_path += ext.arg((int)dev); + + int rc = mknod(tmp_path.latin1(), (S_IFCHR | S_IREAD), dev); + if (rc < 0) return -1; + + int fd = open(tmp_path.latin1(), O_RDONLY); + if (fd < 0) { + unlink(tmp_path.latin1()); + return -1; + } + + if (unlink(tmp_path.latin1()) < 0) { + close(fd); + return -1; + } + + return fd; +} + +#endif + + diff --git a/klaptopdaemon/kpcmcia.h b/klaptopdaemon/kpcmcia.h new file mode 100644 index 0000000..c821926 --- /dev/null +++ b/klaptopdaemon/kpcmcia.h @@ -0,0 +1,214 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef _KPCMCIA_H +#define _KPCMCIA_H + +class QTimer; +class KPCMCIA; + +#include <qmemarray.h> + +#include <sys/types.h> + +#define CARD_STATUS_PRESENT 1 +#define CARD_STATUS_READY 2 +#define CARD_STATUS_BUSY 4 +#define CARD_STATUS_SUSPEND 8 +#define CARD_STATUS_SUSPENDED 8 + + +class KPCMCIACard { +friend class KPCMCIA; +protected: + KPCMCIACard(); + ~KPCMCIACard(); + + int _fd; + + int _interrupt; + QString _device, _ports; + QString _module; + QString _cardname; + QString _type; + int _vcc, _vpp, _vpp2; + QString _stabPath; + int _iotype; + int _inttype; + int _cfgbase; + + int _status; + int _num; + + // Other fields for the future + // etc look in linux/cs.h for more info + +public: + + /** + * Base address for configuration + */ + inline int configBase() { return _cfgbase; } + + /** + * Interrupt type + */ + inline int intType() { return _inttype; } + + /** + * 16/32 bit + */ + inline int busWidth() { return _iotype; } + + /** + * True if the card is present + */ + inline bool present() { return _status & CARD_STATUS_PRESENT; } + + /** + * Return the card status + */ + inline int status() { return _status; } + + /** + * Request to eject the card + */ + int eject(); + + /** + * Request to resume from suspend + */ + int resume(); + + /** + * Request to suspend + */ + int suspend(); + + /** + * Request to reset the card + */ + int reset(); + + /** + * Insert a card (mostly not needed?) + */ + int insert(); + + /** + * Return the card number + */ + inline int num() { return _num; } + + /** + * Return the interrupt in use (or -1 if none) + */ + inline int irq() { return _interrupt; } + + /** + * Return the VCC status + */ + inline int vcc() { return _vcc; } + + /** + * Return the card programming power (1) + */ + inline int vpp() { return _vpp; } + + /** + * Return the card programming power (2) + */ + inline int vpp2() { return _vpp2; } + + /** + * Return the card name + */ + inline QString& name() { return _cardname; } + + /** + * Return the port range + */ + inline QString& ports() { return _ports; } + + /** + * Return the device name + */ + inline QString& device() { return _device; } + + /** + * Return the device type (ie network, modem, etc) + */ + inline QString& type() { return _type; } + + /** + * Return the driver (module) name + */ + inline QString& driver() { return _module; } + + /** + * Refresh the card information - return < 0 on error. + * (this is called automatically [by KPCMCIA] on a timer normally) + */ + int refresh(); + +private: + time_t _last; +}; + + + + +class KPCMCIA : public QObject { +Q_OBJECT +public: + + KPCMCIA(int maxSlots = 8, const char *stabPath = "/var/run/stab"); + ~KPCMCIA(); + + void setRefreshSpeed(int msec); + int getCardCount(); + KPCMCIACard *getCard(int num); + + bool haveCardServices(); + +signals: + void cardUpdated(int num); + + +public slots: + void updateCardInfo(); + +private: + int _refreshSpeed; + QTimer *_timer; + QMemArray<KPCMCIACard *> *_cards; + int _cardCnt; + bool _haveCardServices; + int _maxSlots; + QString _stabPath; + +}; + + + + +#endif + diff --git a/klaptopdaemon/kpcmciainfo.cpp b/klaptopdaemon/kpcmciainfo.cpp new file mode 100644 index 0000000..82da914 --- /dev/null +++ b/klaptopdaemon/kpcmciainfo.cpp @@ -0,0 +1,313 @@ + +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + + +#include <qtabwidget.h> +#include <qlayout.h> +#include <qtimer.h> +#include <kstatusbar.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> + +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include "kpcmcia.h" + +#include "kpcmciainfo.h" + + +KPCMCIAInfo::KPCMCIAInfo(KPCMCIA *pcmcia, QWidget *parent, const char *name) + : KDialog(parent, name, false), _pcmcia(pcmcia) { + + setMinimumSize(300,400); + + _mainGrid = new QGridLayout(this, 9, 5); + + _mainTab = new QTabWidget(this); + _mainGrid->addMultiCellWidget(_mainTab, 0, 6, 0, 4); + _mainGrid->setRowStretch(0, 1); + _mainGrid->setRowStretch(1, 1); + _mainGrid->setRowStretch(2, 1); + _mainGrid->setRowStretch(3, 1); + _mainGrid->setRowStretch(4, 1); + _mainGrid->setRowStretch(5, 1); + _mainGrid->setRowStretch(6, 1); + + setCaption(i18n("PCMCIA & CardBus Slots")); + + prepareCards(); + + _mainTab->resize(KDialog::sizeHint()); + resize(KDialog::sizeHint()); + + connect(_pcmcia, SIGNAL(cardUpdated(int)), this, SLOT(updateCard(int))); + + _sb = new KStatusBar(this); + _sb->insertItem(i18n("Ready."), 0, 1, true); + _sb->resize(KDialog::sizeHint()); + _mainGrid->addMultiCellWidget(_sb, 8, 8, 0, 4); + _mainGrid->setRowStretch(8, 0); + + _updateButton = new QPushButton(i18n("&Update"), this); + _mainGrid->addWidget(_updateButton, 7, 3); + connect(_updateButton, SIGNAL(pressed()), this, SLOT(update())); + _closeButton = new KPushButton(KStdGuiItem::close(), this); + _mainGrid->addWidget(_closeButton, 7, 4); + connect(_closeButton, SIGNAL(pressed()), this, SLOT(slotClose())); + _mainGrid->setRowStretch(7, 0); + + show(); +} + + + +KPCMCIAInfo::~KPCMCIAInfo() { + +} + + +void KPCMCIAInfo::showTab(int num) { + _mainTab->showPage(_pages[num]); +} + + +void KPCMCIAInfo::slotResetStatus() { + _sb->changeItem(i18n("Ready."), 0); +} + + +void KPCMCIAInfo::statusNotice(const QString& text, int life) { + _sb->changeItem(text, 0); + if (life > 0) + QTimer::singleShot(life, this, SLOT(slotResetStatus())); +} + + + +void KPCMCIAInfo::slotTabSetStatus(const QString& text) { + statusNotice(text); +} + + +void KPCMCIAInfo::slotClose() { + delete this; +} + + +void KPCMCIAInfo::update() { + emit updateNow(); +} + + +void KPCMCIAInfo::updateCard(int num) { + _pages[num]->update(); +} + + +void KPCMCIAInfo::prepareCards() { + if (!_pcmcia) { + // FIXME: display error + return; + } + + for (int i = 0; i < _pcmcia->getCardCount(); i++) { + QString tabname = i18n("Card Slot %1"); + KPCMCIAInfoPage *tp = new KPCMCIAInfoPage(_pcmcia->getCard(i), _mainTab); + connect(this, SIGNAL(updateNow()), tp, SLOT(update())); + connect(tp, SIGNAL(setStatusBar(const QString&)), this, SLOT(slotTabSetStatus(const QString&))); + tp->resize(_mainTab->sizeHint()); + _mainTab->addTab(tp, tabname.arg(i+1)); + _pages.insert(i, tp); + } +} + + + + + + +/////////////////////////////////////////////////////////////////////////// + + +KPCMCIAInfoPage::KPCMCIAInfoPage(KPCMCIACard *card, QWidget *parent, const char *name) + : QFrame(parent, name), _card(card) { + _mainGrid = new QGridLayout(this, 10, 10); + if (!_card) { + // display an error + } else { + _card_name = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_name, 0, 0, 0, 5); + _card_type = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_type, 0, 0, 6, 9); + _card_driver = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_driver, 1, 1, 0, 4); + _card_irq = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_irq, 2, 2, 0, 3); + _card_io = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_io, 3, 3, 0, 6); + _card_dev = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_dev, 4, 4, 0, 4); + _card_vcc = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_vcc, 5, 5, 0, 2); + _card_vpp = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_vpp, 5, 5, 5, 9); + _card_bus = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_bus, 6, 6, 0, 4); + _card_cfgbase = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_cfgbase, 6, 6, 5, 9); + + _card_ej_ins = new QPushButton(i18n("&Eject"), this); + _card_sus_res = new QPushButton(i18n("&Suspend"), this); + _card_reset = new QPushButton(i18n("&Reset"), this); + _mainGrid->addWidget(_card_ej_ins, 9, 5); + _mainGrid->addWidget(_card_sus_res, 9, 6); + _mainGrid->addWidget(_card_reset, 9, 7); + connect(_card_reset, SIGNAL(pressed()), this, SLOT(slotResetCard())); + connect(_card_sus_res, SIGNAL(pressed()), this, SLOT(slotSuspendResume())); + connect(_card_ej_ins, SIGNAL(pressed()), this, SLOT(slotInsertEject())); + + update(); + } +} + + +KPCMCIAInfoPage::~KPCMCIAInfoPage() { + +} + + + +void KPCMCIAInfoPage::slotResetCard() { + emit setStatusBar(i18n("Resetting card...")); + _card->reset(); +} + + +void KPCMCIAInfoPage::slotInsertEject() { + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + emit setStatusBar(i18n("Inserting new card...")); + _card->insert(); + _card->reset(); + } else { + emit setStatusBar(i18n("Ejecting card...")); + if (_card->status() & CARD_STATUS_SUSPEND) + _card->resume(); + _card->eject(); + } +} + + +void KPCMCIAInfoPage::slotSuspendResume() { + if (!(_card->status() & CARD_STATUS_BUSY)) + if (!(_card->status() & CARD_STATUS_SUSPEND)) { + emit setStatusBar(i18n("Suspending card...")); + _card->suspend(); + } else { + emit setStatusBar(i18n("Resuming card...")); + _card->resume(); + } +} + + +void KPCMCIAInfoPage::update() { + if (_card) { + QString tmp; + _card_name->setText(_card->name()); + _card_name->resize(_card_name->sizeHint()); + tmp = i18n("Card type: %1 "); + _card_type->setText(tmp.arg(_card->type())); + _card_type->resize(_card_type->sizeHint()); + tmp = i18n("Driver: %1"); + _card_driver->setText(tmp.arg(_card->driver())); + _card_driver->resize(_card_driver->sizeHint()); + tmp = i18n("IRQ: %1%2"); + QString tmp2; + switch (_card->intType()) { + case 1: + tmp2 = i18n(" (used for memory)"); + break; + case 2: + tmp2 = i18n(" (used for memory and I/O)"); + break; + case 4: + tmp2 = i18n(" (used for CardBus)"); + break; + default: + tmp2 = ""; + }; + if (_card->irq() <= 0) + _card_irq->setText(tmp.arg(i18n("none")).arg("")); + else _card_irq->setText(tmp.arg(_card->irq()).arg(tmp2)); + _card_irq->resize(_card_irq->sizeHint()); + tmp = i18n("I/O port(s): %1"); + if (_card->ports().isEmpty()) + _card_io->setText(tmp.arg(i18n("none"))); + else _card_io->setText(tmp.arg(_card->ports())); + _card_io->resize(_card_io->sizeHint()); + tmp = i18n("Bus: %1 bit %2"); + if (_card->busWidth() == 0) + _card_bus->setText(i18n("Bus: unknown")); + else _card_bus->setText(tmp.arg(_card->busWidth()).arg(_card->busWidth() == 16 ? i18n("PC Card") : i18n("Cardbus"))); + _card_bus->resize(_card_bus->sizeHint()); + tmp = i18n("Device: %1"); + _card_dev->setText(tmp.arg(_card->device())); + _card_dev->resize(_card_dev->sizeHint()); + tmp = i18n("Power: +%1V"); + _card_vcc->setText(tmp.arg(_card->vcc()/10)); + _card_vcc->resize(_card_vcc->sizeHint()); + tmp = i18n("Programming power: +%1V, +%2V"); + _card_vpp->setText(tmp.arg(_card->vpp()/10).arg(_card->vpp2()/10)); + _card_vpp->resize(_card_vpp->sizeHint()); + tmp = i18n("Configuration base: 0x%1"); + if (_card->configBase() == 0) + _card_cfgbase->setText(i18n("Configuration base: none")); + else _card_cfgbase->setText(tmp.arg(_card->configBase(), -1, 16)); + _card_cfgbase->resize(_card_cfgbase->sizeHint()); + + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + _card_ej_ins->setText(i18n("&Insert")); + } else { + _card_ej_ins->setText(i18n("&Eject")); + } + if (!(_card->status() & (CARD_STATUS_BUSY|CARD_STATUS_SUSPEND))) { + _card_sus_res->setText(i18n("&Suspend")); + } else { + _card_sus_res->setText(i18n("Resu&me")); + } + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + _card_sus_res->setEnabled(false); + _card_reset->setEnabled(false); + } else { + _card_sus_res->setEnabled(true); + if (!(_card->status() & CARD_STATUS_SUSPEND)) + _card_reset->setEnabled(true); + else _card_reset->setEnabled(false); + } + } +} + + + + +#include "kpcmciainfo.moc" + diff --git a/klaptopdaemon/kpcmciainfo.h b/klaptopdaemon/kpcmciainfo.h new file mode 100644 index 0000000..0cc7cea --- /dev/null +++ b/klaptopdaemon/kpcmciainfo.h @@ -0,0 +1,116 @@ + +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef _KPCMCIAINFO_H +#define _KPCMCIAINFO_H + +#include <kdialog.h> +#include <qframe.h> + +class KPCMCIA; +class KPCMCIACard; +class KPCMCIAInfoPage; +class QTabWidget; +class KStatusBar; +class QGridLayout; +class QPushButton; +class KPushButton; + +#include <qmap.h> + +class KPCMCIAInfo : public KDialog { +Q_OBJECT +public: + + KPCMCIAInfo(KPCMCIA *pcmcia, QWidget *parent = NULL, const char *name = 0); + virtual ~KPCMCIAInfo(); + + void showTab(int num); + void statusNotice(const QString& text, int life = 1500); + +public slots: + void slotClose(); + void update(); + void updateCard(int num); + void slotResetStatus(); + void slotTabSetStatus(const QString& text); + +signals: + void updateNow(); + +private: + QFrame *_mainFrame; + QTabWidget *_mainTab; + QGridLayout *_mainGrid; + KPCMCIA *_pcmcia; + QMap<int,KPCMCIAInfoPage*> _pages; + KStatusBar *_sb; + KPushButton *_closeButton; + QPushButton *_updateButton; + + + void prepareCards(); +}; + + +class QLabel; + + +class KPCMCIAInfoPage : public QFrame { +Q_OBJECT +public: + KPCMCIAInfoPage(KPCMCIACard *card, QWidget *parent = NULL, const char *name = 0); + virtual ~KPCMCIAInfoPage(); + +public slots: + void update(); + void slotResetCard(); + void slotInsertEject(); + void slotSuspendResume(); + +signals: + void setStatusBar(const QString&); + +private: + + KPCMCIACard *_card; + QGridLayout *_mainGrid; + + QLabel *_card_name; + QLabel *_card_type; + QLabel *_card_irq; + QLabel *_card_io; + QLabel *_card_dev; + QLabel *_card_driver; + QLabel *_card_vcc; + QLabel *_card_vpp; + QLabel *_card_cfgbase; + QLabel *_card_bus; + + QPushButton *_card_ej_ins; + QPushButton *_card_sus_res; + QPushButton *_card_reset; + +}; + +#endif + diff --git a/klaptopdaemon/krichtextlabel.cpp b/klaptopdaemon/krichtextlabel.cpp new file mode 100644 index 0000000..458ade6 --- /dev/null +++ b/klaptopdaemon/krichtextlabel.cpp @@ -0,0 +1,112 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "krichtextlabel.h" + +#include <qtooltip.h> +#include <qstylesheet.h> +#include <qsimplerichtext.h> + +#include <kglobalsettings.h> + +static QString qrichtextify( const QString& text ) +{ + if ( text.isEmpty() || text[0] == '<' ) + return text; + + QStringList lines = QStringList::split('\n', text); + for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) + { + *it = QStyleSheet::convertFromPlainText( *it, QStyleSheetItem::WhiteSpaceNormal ); + } + + return lines.join(QString::null); +} + +KRichTextLabel::KRichTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); + setText(text); +} + +KRichTextLabel::KRichTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); +} + +void KRichTextLabel::setDefaultWidth(int defaultWidth) +{ + m_defaultWidth = defaultWidth; + updateGeometry(); +} + +QSizePolicy KRichTextLabel::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum, false); +} + +QSize KRichTextLabel::minimumSizeHint() const +{ + QString qt_text = qrichtextify( text() ); + int pref_width = 0; + int pref_height = 0; + QSimpleRichText rt(qt_text, font()); + pref_width = m_defaultWidth; + rt.setWidth(pref_width); + int used_width = rt.widthUsed(); + if (used_width <= pref_width) + { + while(true) + { + int new_width = (used_width * 9) / 10; + rt.setWidth(new_width); + int new_height = rt.height(); + if (new_height > pref_height) + break; + used_width = rt.widthUsed(); + if (used_width > new_width) + break; + } + pref_width = used_width; + } + else + { + if (used_width > (pref_width *2)) + pref_width = pref_width *2; + else + pref_width = used_width; + } + + return QSize(pref_width, rt.height()); +} + +QSize KRichTextLabel::sizeHint() const +{ + return minimumSizeHint(); +} + +void KRichTextLabel::setText( const QString &text ) { + QLabel::setText(text); +} + +void KRichTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#include "krichtextlabel.moc" diff --git a/klaptopdaemon/krichtextlabel.h b/klaptopdaemon/krichtextlabel.h new file mode 100644 index 0000000..e03fe25 --- /dev/null +++ b/klaptopdaemon/krichtextlabel.h @@ -0,0 +1,65 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KRICHTEXTLABEL_H +#define KRICHTEXTLABEL_H + +#include <qlabel.h> + +#include <kdelibs_export.h> + +/** + * @short A replacement for QLabel that supports richtext and proper layout management + * + * @author Waldo Bastian <[email protected]> + */ + +/* + * QLabel + */ +class KDEUI_EXPORT KRichTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + KRichTextLabel( QWidget *parent, const char *name = 0 ); + KRichTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + int defaultWidth() const { return m_defaultWidth; } + void setDefaultWidth(int defaultWidth); + + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + QSizePolicy sizePolicy() const; + +public slots: + void setText( const QString & ); + +protected: + int m_defaultWidth; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KRichTextLabelPrivate; + KRichTextLabelPrivate *d; +}; + +#endif // KRICHTEXTLABEL_H diff --git a/klaptopdaemon/laptop_check.cpp b/klaptopdaemon/laptop_check.cpp new file mode 100644 index 0000000..7ba7b40 --- /dev/null +++ b/klaptopdaemon/laptop_check.cpp @@ -0,0 +1,53 @@ +/* + * laptop_check.cpp + * Copyright (C) 2003 Paul Campbell <[email protected]> + * + * quick check application - runs from kcminit - makes the check + * to see if kded should be told to run the laptop daemon at + * book time + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "daemon_state.h" +#include <stdlib.h> +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <klocale.h> +static const char description[] = + I18N_NOOP("KDE laptop daemon starter"); + +static const char version[] = "v0.0.1"; + +extern void wake_laptop_daemon(); + +int +main(int argc, char **argv) +{ + KAboutData aboutData( "klaptop_check", I18N_NOOP("KLaptop"), + version, description, KAboutData::License_GPL, + "(c) 2003, Paul Campbell"); + aboutData.addAuthor("Paul Campbell",0, "[email protected]"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication a; + daemon_state s; + s.load(); + if (s.need_to_run()) + wake_laptop_daemon(); + return(0); +} diff --git a/klaptopdaemon/laptop_daemon.cpp b/klaptopdaemon/laptop_daemon.cpp new file mode 100644 index 0000000..6b66a64 --- /dev/null +++ b/klaptopdaemon/laptop_daemon.cpp @@ -0,0 +1,1083 @@ +/* + * laptop_daemon.cpp + * Copyright (C) 1999 Paul Campbell <[email protected]> + * + * this replaces kcmlaptop - there are 2 parts - one is the panels that + * put the setup configuration in the "kcmlaptop" configm, the other + * is the laptop_daemon (this guy) who watches the battery state + * and does stuff as a result + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <stdlib.h> +#include <fcntl.h> + +#include <qtimer.h> + +#include <kconfig.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include "laptop_daemon.h" +#include "portable.h" +#include <kaboutdata.h> +#include <kaudioplayer.h> +#include <kapplication.h> +#include <sys/ioctl.h> +#include <kmessagebox.h> +#include <kpassivepopup.h> +#include <dcopclient.h> +#include <qsocketnotifier.h> +#include <qcursor.h> + +#include <unistd.h> +#include <sys/time.h> + +extern "C" +{ + KDE_EXPORT KDEDModule *create_klaptopdaemon(const QCString& name) { + return new laptop_daemon(name); + } +} + + +class XWidget: public QWidget { +public: + XWidget(laptop_daemon *p):QWidget(0) { pd = p; } +private: + bool x11Event(XEvent *event); + laptop_daemon *pd; +}; +bool XWidget::x11Event(XEvent *event) { return pd->x11Event(event); } + +laptop_daemon::laptop_daemon(const QCString& obj): KDEDModule(obj) +{ + xwidget = new XWidget(this); + xwidget->hide(); + kapp->installX11EventFilter(xwidget); + + mLavEnabled = false; + backoffTimer = 0; + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + wake_timer = 0; + button_bright_saved=0; + button_bright_val=0; + button_saved_performance = 0; + button_saved_throttle = 0; + power_button_off = 0; + + if (laptop_portable::has_brightness()) { + brightness = laptop_portable::get_brightness(); + } else { + brightness = 0; + } + buttonThread.sethandle(this); + triggered[0] = 0; + triggered[1] = 0; + timer = 0; + dock_widget = 0; + oldTimer = 0; + sony_fd = -1; + sony_notifier = 0; + knownFullyCharged = 0; + sony_disp = 0; + connect(this, SIGNAL(signal_checkBattery()), SLOT(checkBatteryNow())); + + //hasAudio = (audioServer.serverStatus() == 0) ? true : false; + + // FIXME: make these configurable. Some system definitely don't + // use /var/run/stab + if (!access("/var/run/stab", R_OK|F_OK)) + _pcmcia = new KPCMCIA(8, "/var/run/stab"); + else if (!access("/var/lib/pcmcia/stab", R_OK|F_OK)) + _pcmcia = new KPCMCIA(8, "/var/lib/pcmcia/stab"); + else _pcmcia = NULL; + + if (_pcmcia) + connect(_pcmcia, SIGNAL(cardUpdated(int)), this, SLOT(updatePCMCIA(int))); + connect( &autoLock, SIGNAL(timeout()), this, SLOT(timerDone()) ); + +} + +laptop_daemon::~laptop_daemon() +{ + delete xwidget; + delete _pcmcia; + delete dock_widget; + delete sony_notifier; + if (sony_disp) + XCloseDisplay(sony_disp); +} + +void +laptop_daemon::quit() +{ + deleteLater(); +} + +void laptop_daemon::restart() +{ + if (oldTimer > 0) { + killTimer(oldTimer); + oldTimer=0; + } + if (timer) { + autoLock.stop(); + timer = 0; + } + s.load(); + if (s.has_brightness) { + brightness = laptop_portable::get_brightness(); + } else { + brightness = 0; + } + + if (!s.need_to_run()) { + quit(); + return; + } + + if (sony_fd < 0) + sony_fd = ::open("/dev/sonypi", O_RDONLY|O_NONBLOCK); + if (s.sony_enablescrollbar||s.sony_middleemulation) { + if (sony_disp == 0 && sony_fd >= 0) + sony_disp = XOpenDisplay(NULL); + if (sony_fd < 0 || sony_disp == 0) { + s.sony_enablescrollbar = 0; + s.sony_middleemulation = 0; + } + } + + // change the dock state if necessary + + if (s.enabled) { + if (!dock_widget) { + dock_widget = new laptop_dock(this); + dock_widget->setPCMCIA(_pcmcia); + dock_widget->show(); + } + dock_widget->reload_icon(); + dock_widget->SetupPopup(); + } else { + if (dock_widget) { + delete dock_widget; + dock_widget = 0; + } + } + + if (s.enable_lid_button && (lid_state = laptop_portable::get_button(laptop_portable::LidButton))) { + if (s.button_lid_bright_enabled) + SetBrightness(0, s.button_lid_bright_val); + if (s.button_lid_performance_enabled) + SetPerformance(s.button_lid_performance_val); + if (s.button_lid_throttle_enabled) + SetThrottle(s.button_lid_throttle_val); + switch (s.button_lid) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } + if (s.enable_power_button && (power_state = laptop_portable::get_button(laptop_portable::PowerButton))) { + if (s.button_power_bright_enabled) + SetBrightness(0, s.button_power_bright_val); + if (s.button_power_performance_enabled) + SetPerformance(s.button_power_performance_val); + if (s.button_power_throttle_enabled) + SetThrottle(s.button_power_throttle_val); + switch (s.button_power) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } + if (s.button_power_bright_enabled || s.button_power_performance_enabled || s.button_power_throttle_enabled || + s.button_lid_bright_enabled || s.button_lid_performance_enabled || s.button_lid_throttle_enabled || + s.button_lid != 0 || s.button_power != 0) { // need a fast thread to poll every sec + if (!buttonThread.running()) { + buttonThread.start(); + } + } else { + if (buttonThread.running()) { + buttonThread.quit(); + buttonThread.done(); + } + } + + + // Do setup + struct power_result p = laptop_portable::poll_battery_state(); + powered = p.powered; + + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + if (s.power_action[0] || s.power_action[1] || s.power_brightness_enabled[0] || s.power_brightness_enabled[0] || + s.power_performance_enabled[0] || s.power_performance_enabled[1] || s.power_throttle_enabled[0] || s.power_throttle_enabled[1]) { + power_time = s.power_wait[powered?0:1]; + timer = 1; + setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]); + autoLock.setTimeout(power_time); + autoLock.start(); + } else { + timer = 0; + } + + + if (s.useBlankSaver) { + setBlankSaver(!p.powered); + } + + start_monitor(); + + // brightness control + + if (s.has_brightness) { + if (s.bright_pon && powered) { + SetBrightness(0, s.bright_son); + } else + if (s.bright_poff && !powered) { + SetBrightness(0, s.bright_soff); + } + } + if (s.has_performance) { + if (s.performance_pon && powered) { + SetPerformance(s.performance_val_on); + } else + if (s.performance_poff && !powered) { + SetPerformance(s.performance_val_off); + } + } + if (s.has_throttle) { + if (s.throttle_pon && powered) { + SetThrottle(s.throttle_val_on); + } else + if (s.throttle_poff && !powered) { + SetThrottle(s.throttle_val_off); + } + } + + // sony support + + if (s.sony_enablescrollbar||s.sony_middleemulation) { + if (sony_notifier == 0) { + sony_notifier = new QSocketNotifier( sony_fd, QSocketNotifier::Read, this ); + if (sony_notifier) + QObject::connect( sony_notifier, SIGNAL(activated(int)), + this, SLOT(sonyDataReceived()) ); + } + } else { + if (sony_notifier) { + delete sony_notifier; + sony_notifier = 0; + } + } +} + + +void laptop_daemon::setBlankSaver(bool blanked) +{ + QByteArray ba; + QDataStream ds(ba, IO_WriteOnly); + ds << bool(blanked); + // can't use kapp->dcopClient() because it breaks KUniqueApplication + DCOPClient c; + c.attach(); + c.send("kdesktop", "KScreensaverIface", "setBlankOnly(bool)", ba); + c.detach(); +} + + +void laptop_daemon::timerDone() +{ + if (mLavEnabled && laptop_portable::get_load_average() >= mLav) { + autoLock.postpone(); // will call timerDone() again later + return; + } + int action; + + timer = 0; + autoLock.stop(); // stop - see the note below about backoff + if (powered) { + action = s.power_action[0]; + } else { + action = s.power_action[1]; + } + switch (action) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + } + if ((powered?s.power_brightness_enabled[0]:s.power_brightness_enabled[1])) { + need_wait = 1; + if (!saved_brightness) { + saved_brightness = 1; + saved_brightness_val = brightness; + } + SetBrightness(1, powered?s.power_brightness[0]:s.power_brightness[1]); + } + if ((powered?s.power_performance_enabled[0]:s.power_performance_enabled[1])) { + need_wait = 1; + if (!saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + saved_performance = 1; + saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(powered?s.power_performance[0]:s.power_performance[1]); + } + if ((powered?s.power_throttle_enabled[0]:s.power_throttle_enabled[1])) { + need_wait = 1; + if (!saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + saved_throttle = 1; + saved_throttle_val = profile_list[current_profile]; + } + } + SetPerformance(powered?s.power_throttle[0]:s.power_throttle[1]); + } + // + // we must give ourself enough time to handle any necessary evil before we start looking again + // (many of the above things cause unexpected time discontinuities) + // + if (need_wait) { + wakepos.setX(QCursor::pos().x()); + wakepos.setY(QCursor::pos().y()); + if (!wake_timer) { + wake_timer = new QTimer(this); + connect(wake_timer, SIGNAL(timeout()), this, SLOT(WakeCheck())); + wake_timer->start(1*1000, 1); + } + } else { + if (!backoffTimer) { + backoffTimer = new QTimer(this); + connect(backoffTimer, SIGNAL(timeout()), this, SLOT(BackoffRestart())); + backoffTimer->start(60*1000, 1); + } + } +} + +void +laptop_daemon::BackoffRestart() +{ + delete backoffTimer; + backoffTimer = 0; + if (!timer) { + timer = 1; + autoLock.start(); + } +} + +void +laptop_daemon::WakeCheck() +{ + if (!wake_timer) + return; + if (!need_wait) { + wake_timer->stop(); + delete wake_timer; + wake_timer = 0; + return; + } + if (wakepos.x() != QCursor::pos().x() || wakepos.y() != QCursor::pos().y()) { + wake_timer->stop(); + delete wake_timer; + wake_timer = 0; + WakeUpAuto(); + } +} + +void +laptop_daemon::WakeUpAuto() +{ + if (!need_wait) + return; + need_wait = 0; + if (saved_brightness) { + SetBrightness(0, saved_brightness_val); + saved_brightness = 0; + } + if (saved_throttle) { + SetThrottle(saved_throttle_val); + saved_throttle = 0; + } + if (saved_performance) { + SetPerformance(saved_performance_val); + saved_performance = 0; + } + if (!timer) { + timer = 1; + autoLock.start(); + } +} + +bool +laptop_daemon::x11Event(XEvent *event) +{ + switch (event->type) { + case KeyPress: + case ButtonPress: + if (need_wait) + WakeUpAuto(); + break; + + } + return(0); +} + +void laptop_daemon::dock_quit() +{ + if (dock_widget) + delete dock_widget; + dock_widget = 0; +} + + +void laptop_daemon::updatePCMCIA(int num) +{ + Q_UNUSED(num); + //kdDebug() << "PCMCIA card " << num << " was updated." << endl; + + // Two things we do here. We provide notifications for cards + // being inserted / cards going to sleep / cards waking up + // and cards being safe to eject. + // The second thing we do is provide the desktop icon actions + // via dcop. +} + + +void laptop_daemon::haveBatteryLow(int t, const int num, const int type) +{ + displayPixmap(); + + // beep if we are allowed to + if (s.systemBeep[t]) { + //KNotifyClient::beep(); + (void)kapp->beep(); + } + + // run a command if we have to + if (s.runCommand[t]) { + // make sure the command exists + if (!s.runCommandPath[t].isEmpty()) { + KProcess command; + command << s.runCommandPath[t]; + command.start(KProcess::DontCare); + } + } + + if (s.do_brightness[t]) + SetBrightness(0, s.val_brightness[t]); + if (s.do_throttle[t]) + SetThrottle(s.val_throttle[t]); + if (s.do_performance[t]) + SetPerformance(s.val_performance[t]); + + // play a sound if we have to + if (s.playSound[t]) { + KAudioPlayer::play(s.playSoundPath[t]); + } + + + if (s.do_hibernate[t]) + invokeHibernate(); + if (s.do_suspend[t]) + invokeSuspend(); + if (s.do_standby[t]) + invokeStandby(); + if (s.logout[t]) + invokeLogout(); + if (s.shutdown[t]) + invokeShutdown(); + // notify if we must (must be last since it's synchronous) + if (s.notify[t]) { + if (type) { + if (s.time_based_action_critical) { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("%1 % charge left.").arg(num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } else { + // Will this ever be reached? + KPassivePopup::message(i18n("Battery power is running out."), + i18n("%1 % charge left.").arg(num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } + } + else { + if (s.time_based_action_low) { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("1 minute left.","%n minutes left.", num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } else { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("1% left.", "%n percent left.", num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } + } + } +} + +int laptop_daemon::calcBatteryTime(int percent, long time, bool restart) +{ +#define MAX_SAMPLES_USED 3 + static int percents[MAX_SAMPLES_USED]; + static long times[MAX_SAMPLES_USED]; + static int lastused=-1; + int r=-1; + + if ( (lastused==-1) || restart ) + { + percents[0]=percent; + times[0]=time; + lastused=0; + } + else + { + // Add the % and time to the arrays + // (or just update the time if the % hasn't changed) + if (percents[lastused]!=percent) + if (lastused!=MAX_SAMPLES_USED-1) + { + lastused++; + percents[lastused]=percent; + times[lastused]=time; + } + else + { + for (int i=1;i<MAX_SAMPLES_USED;i++) + { percents[i-1]=percents[i]; times[i-1]=times[i]; }; + } + percents[lastused]=percent; + times[lastused]=time; + + //Now let's do the real calculations + + if (lastused==0) return -1; + + // Copy the data to temporary variables + double tp[MAX_SAMPLES_USED]; + double tt[MAX_SAMPLES_USED]; + + for (int i=0;i<=lastused;i++) + { tp[i]=percents[i]; tt[i]=times[i]; }; + + for (int c=lastused; c>1; c--) + { + for (int i=0; i<c-1; i++) + { + tp[i]=(tp[i]+tp[i+1])/2; + tt[i]=(tt[i]+tt[i+1])/2; + } + } + + // Now we've reduced all the samples to an approximation with just a line + + if (tp[1]-tp[0]!=0) + r=static_cast<int>(tt[0]-(tp[0]/(tp[1]-tp[0]))*(tt[1]-tt[0])-time); + + + } + + return r; +} + +void laptop_daemon::checkBatteryNow() +{ + struct power_result p; + + p = laptop_portable::poll_battery_state(); + + if (s.useBlankSaver && oldpowered != p.powered) { + setBlankSaver(!p.powered); + } + + powered = p.powered; + left = p.time; + val = p.percentage; + + if (oldpowered != powered && s.has_brightness) { + if (s.bright_pon && powered) { + SetBrightness(0, s.bright_son); + } else + if (s.bright_poff && !powered) { + SetBrightness(0, s.bright_soff); + } + if (s.performance_pon && powered) { + SetPerformance(s.performance_val_on); + } else + if (s.performance_poff && !powered) { + SetPerformance(s.performance_val_off); + } + if (s.throttle_pon && powered) { + SetThrottle(s.throttle_val_on); + } else + if (s.throttle_poff && !powered) { + SetThrottle(s.throttle_val_off); + } + + } + + if (left==-1) // Let's try to calculate the expected battery time left + { + timeval tv; + gettimeofday(&tv, 0); + left=calcBatteryTime(((powered)?100-val:val), tv.tv_sec, oldpowered!=powered ); + } + + if (timer && oldpowered != powered) { + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]); + if (power_time != s.power_wait[powered?0:1]) { + power_time = s.power_wait[powered?0:1]; + autoLock.stop(); + autoLock.setTimeout(power_time); + autoLock.start(); + } + } + if (!knownFullyCharged) { + knownFullyCharged = 1; + } else + if (s.notifyMeWhenFull && oldval != val && val == 100) + KMessageBox::queuedMessageBox(0, KMessageBox::Information, i18n("Your battery is now fully charged."), i18n("Laptop Battery")); + changed = oldpowered != powered||oldexists != s.exists||oldval != val || oldleft!=left; + oldpowered = powered; + oldexists = s.exists; + oldval = val; + oldleft = left; + if (changed) + displayPixmap(); +} + +void laptop_daemon::start_monitor() +{ + checkBatteryNow(); + displayPixmap(); + oldTimer = startTimer(s.poll * 1000); +} + +void laptop_daemon::setPollInterval(const int interval) +{ + s.poll = interval; + + // Kill any old timers that may be running + if (oldTimer > 0) { + killTimer(oldTimer); + + // Start a new timer will the specified time + oldTimer = startTimer(interval * 1000); + + emit(signal_checkBattery()); + } +} + +void laptop_daemon::timerEvent(QTimerEvent *) +{ + emit(signal_checkBattery()); +} + +void laptop_daemon::displayPixmap() +{ + if (s.have_time == 2 && s.exists && !powered) { // in some circumstances + s.have_time = (val < 0 ? 0 : 1); // the battery is not charging + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryLow"); // we can;t figure this out 'till + config->writeEntry("HaveTime", s.have_time); + config->sync(); + delete config; + } + } + + if (dock_widget) + dock_widget->displayPixmap(); + + if (left >= 0) { + if (!triggered[0]) { + if (s.time_based_action_low) { + if (s.exists && !powered && left <= s.low[0]) { + triggered[0] = 1; + haveBatteryLow(0, left, 0); + } + } else { + if (s.exists && !powered && val <= s.low[1]) { + triggered[0] = 1; + haveBatteryLow(0, val, 0); + } + } + } + if (!triggered[1]) { + if (s.time_based_action_critical) { + if (s.exists && !powered && left <= s.low[2]) { + triggered[1] = 1; + haveBatteryLow(1, left, 0); + } + } else { + if (s.exists && !powered && val <= s.low[3]) { + triggered[1] = 1; + haveBatteryLow(1, val, 0); + } + } + } + } + + if (s.time_based_action_low || s.time_based_action_critical) { + if (left > (s.low[2]+1)) + triggered[1] = 0; + if (left > s.low[0]) + triggered[0] = 0; + } else { + if (val > (s.low[3]+1)) + triggered[1] = 0; + if (val > s.low[1]) + triggered[0] = 0; + } + + if (s.have_time != 1) { + if (!triggered[0]) { + if (s.exists && !powered && val <= s.low[0]) { + triggered[0] = 1; + haveBatteryLow(0, val, 1); + } + } else { + if (!triggered[1]) { + if (s.exists && !powered && val <= s.low[1]) { + triggered[1] = 1; + haveBatteryLow(1, val, 1); + } + } + if (val > (s.low[1]+1)) + triggered[1] = 0; + if (val > s.low[0]) + triggered[0] = 0; + } + } +} + +void laptop_daemon::invokeStandby() +{ + laptop_portable::invoke_standby(); +} + +void laptop_daemon::invokeSuspend() +{ + laptop_portable::invoke_suspend(); +} + +void laptop_daemon::invokeHibernate() +{ + laptop_portable::invoke_hibernation(); +} + +void laptop_daemon::invokeLogout() +{ + bool rc = kapp->requestShutDown(KApplication::ShutdownConfirmNo, KApplication::ShutdownTypeNone, KApplication::ShutdownModeForceNow); + if (!rc) + KMessageBox::sorry(0, i18n("Logout failed.")); +} + +void laptop_daemon::invokeShutdown() +{ + bool rc = kapp->requestShutDown(KApplication::ShutdownConfirmNo, KApplication::ShutdownTypeHalt, KApplication::ShutdownModeForceNow); + if (!rc) + KMessageBox::sorry(0, i18n("Shutdown failed.")); +} + +/* + * Portions of the following code borrowed with thanks from: + * + * Sony Programmable I/O Control Device driver for VAIO. + * Userspace X11 Daemon Utility + * + * Copyright 2001 Stelian Pop, Alcove + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +static void simulateButton(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, True, 0); + XTestFakeButtonEvent(disp, button, False, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +static void simulateButtonDown(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, True, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +static void simulateButtonUp(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, False, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +#define SONYPI_EVENT_JOGDIAL_DOWN 1 +#define SONYPI_EVENT_JOGDIAL_UP 2 +#define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED 3 +#define SONYPI_EVENT_JOGDIAL_UP_PRESSED 4 +#define SONYPI_EVENT_JOGDIAL_PRESSED 5 +#define SONYPI_EVENT_JOGDIAL_RELEASED 6 + +void laptop_daemon::sonyDataReceived() +{ + unsigned char event; + + if (::read(sony_fd, &event, sizeof(event)) != sizeof(event)) + return; + switch(event) { + case SONYPI_EVENT_JOGDIAL_UP: + if (sony_disp && s.sony_enablescrollbar) { + simulateButton(sony_disp, 4); + } + break; + case SONYPI_EVENT_JOGDIAL_DOWN: + if (sony_disp && s.sony_enablescrollbar) { + simulateButton(sony_disp, 5); + } + break; + case SONYPI_EVENT_JOGDIAL_PRESSED: + if (sony_disp && s.sony_middleemulation) { + simulateButtonDown(sony_disp, 2); + } + break; + case SONYPI_EVENT_JOGDIAL_RELEASED: + if (sony_disp && s.sony_middleemulation) { + simulateButtonUp(sony_disp, 2); + } + break; + default: + break; + } +} + +void laptop_daemon::SetBrightness(bool blank, int v) +{ + if (v < 0) + return; + brightness = v; + laptop_portable::set_brightness(blank, v); +} + +void laptop_daemon::SetThrottle(QString v) +{ + laptop_portable::set_system_throttling(v); +} + +void laptop_daemon::SetPerformance(QString v) +{ + laptop_portable::set_system_performance(v); +} + +void +ButtonThread::run() +{ + while (!quitting) { + handle->ButtonThreadInternals(); + msleep(500); // have to run fast because if the power button is held down for too long + } // the system actually gets powered off +} + +void +laptop_daemon::ButtonThreadInternals() +{ + // + // the lid button turns stuff on when it's down and back off again when it's raised + // (kind of like the fridge door light) + // + if (lid_state != laptop_portable::get_button(laptop_portable::LidButton)) { + lid_state = !lid_state; + if (lid_state) { + if (s.button_lid_bright_enabled) { + if (!button_bright_val) + button_bright_val = brightness; + button_bright_saved = 1; + SetBrightness(1, s.button_lid_bright_val); + } + if (s.button_lid_performance_enabled) { + if (!button_saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + button_saved_performance = 1; + button_saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(s.button_lid_performance_val); + } + if (s.button_lid_throttle_enabled) { + if (!button_saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + button_saved_throttle = 1; + button_saved_throttle_val = profile_list[current_profile]; + } + } + SetThrottle(s.button_lid_throttle_val); + } + switch (s.button_lid) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } else { + if (button_bright_saved) { + SetBrightness(0, button_bright_val); + button_bright_saved = 0; + } + if (button_saved_performance) { + button_saved_performance = 0; + SetPerformance( button_saved_performance_val); + } + if (button_saved_throttle) { + button_saved_throttle = 0; + SetThrottle(button_saved_throttle_val); + } + } + } + // + // the power button on the other hand is an off/on switch for non-suspend type ops + // + if (power_state != laptop_portable::get_button(laptop_portable::PowerButton)) { + power_state = !power_state; + if (power_state) { + if (power_button_off) { + if (button_bright_saved) { + SetBrightness(0, button_bright_val); + button_bright_saved = 0; + } + if (button_saved_performance) { + button_saved_performance = 0; + SetPerformance( button_saved_performance_val); + } + if (button_saved_throttle) { + button_saved_throttle = 0; + SetThrottle(button_saved_throttle_val); + } + } else { + if (s.button_power_bright_enabled) { + if (!button_bright_val) + button_bright_val = brightness; + button_bright_saved = 1; + SetBrightness(1, s.button_power_bright_val); + } + if (s.button_power_performance_enabled) { + if (!button_saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + button_saved_performance = 1; + button_saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(s.button_power_performance_val); + } + if (s.button_power_throttle_enabled) { + if (!button_saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + button_saved_throttle = 1; + button_saved_throttle_val = profile_list[current_profile]; + } + } + SetThrottle(s.button_power_throttle_val); + } + } + switch (s.button_power) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + power_button_off = !power_button_off; + } + } +} + +#include "laptop_daemon.moc" diff --git a/klaptopdaemon/laptop_daemon.h b/klaptopdaemon/laptop_daemon.h new file mode 100644 index 0000000..b1537e1 --- /dev/null +++ b/klaptopdaemon/laptop_daemon.h @@ -0,0 +1,186 @@ +#ifndef LAPTOPDAEMON +#define LAPTOPDAEMON 1 +/* + * laptop_daemon.h + * Copyright (C) 1999 Paul Campbell <[email protected]> + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "daemon_state.h" + +#include <qdir.h> +#include <unistd.h> +#include <time.h> +#include <qmovie.h> +#include <qptrlist.h> +#include <qfileinfo.h> +#include <qimage.h> + +#include <kiconloader.h> +#include <kprocess.h> +//#include <kaudio.h> +#include <qtooltip.h> + +#include <X11/Xlib.h> +#include <X11/extensions/XTest.h> + +#include <qsocketnotifier.h> + + + +#include <kdebug.h> +#include <qthread.h> + +#include "kpcmcia.h" + +#include "daemondock.h" +#include "xautolock.h" +#include <kdedmodule.h> + + +class laptop_daemon; +class XWidget; + +class ButtonThread : public QThread { +public: + ButtonThread() { quitting = 0; } + void sethandle(laptop_daemon *h) { handle = h; } + void quit() { quitting = 1; } // make it quit + void done() { while (!finished()) msleep(100); quitting = 0; }// wait 'till it's done + virtual void run(); +private: + bool quitting; + laptop_daemon *handle; +}; + +class laptop_dock; +class laptop_daemon: public KDEDModule +{ + Q_OBJECT + K_DCOP +public: + laptop_daemon(const QCString& obj); + ~laptop_daemon(); + void setPollInterval(const int poll=60); + void SetBrightness(bool blank, int v); // routine to do it + int GetBrightness() { return brightness; } + void SetThrottle(QString v); + void SetPerformance(QString v); + void ButtonThreadInternals(); +k_dcop: + void restart(); + void quit(); +signals: + void signal_checkBattery(); +protected: + void timerEvent(QTimerEvent *); +protected slots: + void checkBatteryNow(); + void timerDone(); + void dock_quit(); + void updatePCMCIA(int num); + void sonyDataReceived(); + void BackoffRestart(); + void WakeCheck(); +private: + void haveBatteryLow(int t, const int num, const int type); + int calcBatteryTime(int percent, long time, bool restart); + void start_monitor(); + void invokeStandby(); + void invokeSuspend(); + void invokeHibernate(); + void invokeShutdown(); + void invokeLogout(); + void displayPixmap(); + void setBlankSaver(bool); + void setLoadAverage(bool enable, float value) {mLavEnabled=enable&&(value>=0.0); mLav=value;} + + laptop_dock *dock_widget; + + // Capability + bool hasAudio; + //KAudio audioServer; + + // General settings +public: + int val; + int powered; + int left; + bool x11Event(XEvent *event); + bool exists() { return s.exists; } + QString noBatteryIcon() { return s.noBatteryIcon; } + QString chargeIcon() { return s.chargeIcon; } + QString noChargeIcon() { return s.noChargeIcon; } +protected: + int triggered[2]; + + int oldval, oldexists, oldpowered, oldleft, knownFullyCharged; + + int changed; + + int oldTimer; + bool timer; // autolock timer is active + + int power_time; + + // PCMCIA related + KPCMCIA *_pcmcia; + + // sony jog-bar support + + int sony_fd; // file desc form open /dev/sonypi + Display *sony_disp; // X display + QSocketNotifier *sony_notifier; // how we know data is waiting + + // brightness + + int brightness; // actual brightness, -1 if not known + + bool lid_state; + bool power_state; + ButtonThread buttonThread; + + + // + XAutoLock autoLock; // timer/UI maint + float mLav; + bool mLavEnabled; + bool need_wait; // undo sleep stuff + bool saved_brightness, saved_throttle, saved_performance; + int saved_brightness_val; + QString saved_performance_val, saved_throttle_val; + QTimer *wake_timer; // the timer for the above running + QPoint wakepos; // the mouse pos at the beginning of time + void WakeUpAuto(); + QTimer *backoffTimer; // backoff + + bool power_button_off; // imagined state of the power button + bool button_bright_saved; // saved button state + int button_bright_val; + bool button_saved_performance; + QString button_saved_performance_val; + bool button_saved_throttle; + QString button_saved_throttle_val; + + daemon_state s; // saved daemon state from config file + + XWidget *xwidget; +}; +#endif diff --git a/klaptopdaemon/linux/bulkmem.h b/klaptopdaemon/linux/bulkmem.h new file mode 100644 index 0000000..e0bafc8 --- /dev/null +++ b/klaptopdaemon/linux/bulkmem.h @@ -0,0 +1,184 @@ +/* + * Definitions for bulk memory services + * + * bulkmem.h 1.8 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + * bulkmem.h 1.3 1995/05/27 04:49:49 + */ + +#ifndef _LINUX_BULKMEM_H +#define _LINUX_BULKMEM_H + +/* For GetFirstRegion and GetNextRegion */ +typedef struct region_info_t { + u_int Attributes; + u_int CardOffset; + u_int RegionSize; + u_int AccessSpeed; + u_int BlockSize; + u_int PartMultiple; + u_char JedecMfr, JedecInfo; + memory_handle_t next; +} region_info_t; + +#define REGION_TYPE 0x0001 +#define REGION_TYPE_CM 0x0000 +#define REGION_TYPE_AM 0x0001 +#define REGION_PREFETCH 0x0008 +#define REGION_CACHEABLE 0x0010 +#define REGION_BAR_MASK 0xe000 +#define REGION_BAR_SHIFT 13 + +/* For OpenMemory */ +typedef struct open_mem_t { + u_int Attributes; + u_int Offset; +} open_mem_t; + +/* Attributes for OpenMemory */ +#define MEMORY_TYPE 0x0001 +#define MEMORY_TYPE_CM 0x0000 +#define MEMORY_TYPE_AM 0x0001 +#define MEMORY_EXCLUSIVE 0x0002 +#define MEMORY_PREFETCH 0x0008 +#define MEMORY_CACHEABLE 0x0010 +#define MEMORY_BAR_MASK 0xe000 +#define MEMORY_BAR_SHIFT 13 + +typedef struct eraseq_entry_t { + memory_handle_t Handle; + u_char State; + u_int Size; + u_int Offset; + void *Optional; +} eraseq_entry_t; + +typedef struct eraseq_hdr_t { + int QueueEntryCnt; + eraseq_entry_t *QueueEntryArray; +} eraseq_hdr_t; + +#define ERASE_QUEUED 0x00 +#define ERASE_IN_PROGRESS(n) (((n) > 0) && ((n) < 0x80)) +#define ERASE_IDLE 0xff +#define ERASE_PASSED 0xe0 +#define ERASE_FAILED 0xe1 + +#define ERASE_MISSING 0x80 +#define ERASE_MEDIA_WRPROT 0x84 +#define ERASE_NOT_ERASABLE 0x85 +#define ERASE_BAD_OFFSET 0xc1 +#define ERASE_BAD_TECH 0xc2 +#define ERASE_BAD_SOCKET 0xc3 +#define ERASE_BAD_VCC 0xc4 +#define ERASE_BAD_VPP 0xc5 +#define ERASE_BAD_SIZE 0xc6 + +/* For CopyMemory */ +typedef struct copy_op_t { + u_int Attributes; + u_int SourceOffset; + u_int DestOffset; + u_int Count; +} copy_op_t; + +/* For ReadMemory and WriteMemory */ +typedef struct mem_op_t { + u_int Attributes; + u_int Offset; + u_int Count; +} mem_op_t; + +#define MEM_OP_BUFFER 0x01 +#define MEM_OP_BUFFER_USER 0x00 +#define MEM_OP_BUFFER_KERNEL 0x01 +#define MEM_OP_DISABLE_ERASE 0x02 +#define MEM_OP_VERIFY 0x04 + +/* For RegisterMTD */ +typedef struct mtd_reg_t { + u_int Attributes; + u_int Offset; + u_long MediaID; +} mtd_reg_t; + +/* + * Definitions for MTD requests + */ + +typedef struct mtd_request_t { + u_int SrcCardOffset; + u_int DestCardOffset; + u_int TransferLength; + u_int Function; + u_long MediaID; + u_int Status; + u_int Timeout; +} mtd_request_t; + +/* Fields in MTD Function */ +#define MTD_REQ_ACTION 0x003 +#define MTD_REQ_ERASE 0x000 +#define MTD_REQ_READ 0x001 +#define MTD_REQ_WRITE 0x002 +#define MTD_REQ_COPY 0x003 +#define MTD_REQ_NOERASE 0x004 +#define MTD_REQ_VERIFY 0x008 +#define MTD_REQ_READY 0x010 +#define MTD_REQ_TIMEOUT 0x020 +#define MTD_REQ_LAST 0x040 +#define MTD_REQ_FIRST 0x080 +#define MTD_REQ_KERNEL 0x100 + +/* Status codes */ +#define MTD_WAITREQ 0x00 +#define MTD_WAITTIMER 0x01 +#define MTD_WAITRDY 0x02 +#define MTD_WAITPOWER 0x03 + +/* + * Definitions for MTD helper functions + */ + +/* For MTDModifyWindow */ +typedef struct mtd_mod_win_t { + u_int Attributes; + u_int AccessSpeed; + u_int CardOffset; +} mtd_mod_win_t; + +/* For MTDSetVpp */ +typedef struct mtd_vpp_req_t { + u_char Vpp1, Vpp2; +} mtd_vpp_req_t; + +/* For MTDRDYMask */ +typedef struct mtd_rdy_req_t { + u_int Mask; +} mtd_rdy_req_t; + +enum mtd_helper { + MTDRequestWindow, MTDModifyWindow, MTDReleaseWindow, + MTDSetVpp, MTDRDYMask +}; + +#ifdef IN_CARD_SERVICES +extern int MTDHelperEntry(int func, void *a1, void *a2); +#else +extern int MTDHelperEntry(int func, ...); +#endif + +#endif /* _LINUX_BULKMEM_H */ diff --git a/klaptopdaemon/linux/ciscode.h b/klaptopdaemon/linux/ciscode.h new file mode 100644 index 0000000..1c536d1 --- /dev/null +++ b/klaptopdaemon/linux/ciscode.h @@ -0,0 +1,96 @@ +/* + * ciscode.h 1.31 1999/02/16 01:16:46 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISCODE_H +#define _LINUX_CISCODE_H + +/* Manufacturer and Product ID codes */ + +#define MANFID_3COM 0x0101 +#define PRODID_3COM_3CXEM556 0x0035 +#define PRODID_3COM_3CCFEM556 0x0556 +#define PRODID_3COM_3C562 0x0562 + +#define MANFID_ADAPTEC 0x012f +#define PRODID_ADAPTEC_SCSI 0x0001 + +#define MANFID_ATT 0xffff +#define PRODID_ATT_KIT 0x0100 + +#define MANFID_CONTEC 0xc001 + +#define MANFID_FUJITSU 0x0004 +#define PRODID_FUJITSU_MBH10302 0x0004 +#define PRODID_FUJITSU_MBH10304 0x1003 +#define PRODID_FUJITSU_LA501 0x2000 + +#define MANFID_IBM 0x00a4 +#define PRODID_IBM_HOME_AND_AWAY 0x002e + +#define MANFID_INTEL 0x0089 +#define PRODID_INTEL_DUAL_RS232 0x0301 +#define PRODID_INTEL_2PLUS 0x8422 + +#define MANFID_LINKSYS 0x0143 +#define PRODID_LINKSYS_PCMLM28 0xc0ab +#define PRODID_LINKSYS_3400 0x3341 + +#define MANFID_MEGAHERTZ 0x0102 +#define PRODID_MEGAHERTZ_VARIOUS 0x0000 +#define PRODID_MEGAHERTZ_EM3288 0x0006 + +#define MANFID_MACNICA 0xc00b + +#define MANFID_MOTOROLA 0x0109 +#define PRODID_MOTOROLA_MARINER 0x0501 + +#define MANFID_NEW_MEDIA 0x0057 + +#define MANFID_OLICOM 0x0121 +#define PRODID_OLICOM_OC2231 0x3122 +#define PRODID_OLICOM_OC2232 0x3222 + +#define MANFID_OMEGA 0x0137 +#define PRODID_OMEGA_QSP_100 0x0025 + +#define MANFID_OSITECH 0x0140 +#define PRODID_OSITECH_JACK_144 0x0001 +#define PRODID_OSITECH_JACK_288 0x0002 +#define PRODID_OSITECH_JACK_336 0x0007 + +#define MANFID_PSION 0x016c + +#define MANFID_QUATECH 0x0137 +#define PRODID_QUATECH_DUAL_RS232 0x0012 +#define PRODID_QUATECH_DUAL_RS232_D1 0x0007 +#define PRODID_QUATECH_QUAD_RS232 0x001b + +#define MANFID_SMC 0x0108 +#define PRODID_SMC_ETHER 0x0105 + +#define MANFID_SOCKET 0x0104 +#define PRODID_SOCKET_DUAL_RS232 0x0006 +#define PRODID_SOCKET_LPE 0x000d + +#define MANFID_SUNDISK 0x0045 + +#define MANFID_TDK 0x0105 + +#define MANFID_XIRCOM 0x0105 + +#endif /* _LINUX_CISCODE_H */ diff --git a/klaptopdaemon/linux/cisreg.h b/klaptopdaemon/linux/cisreg.h new file mode 100644 index 0000000..ebe54fc --- /dev/null +++ b/klaptopdaemon/linux/cisreg.h @@ -0,0 +1,105 @@ +/* + * cisreg.h 1.11 1998/09/11 08:54:47 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISREG_H +#define _LINUX_CISREG_H + +/* Offsets from ConfigBase for CIS registers */ +#define CISREG_COR 0x00 +#define CISREG_CCSR 0x02 +#define CISREG_PRR 0x04 +#define CISREG_SCR 0x06 +#define CISREG_ESR 0x08 +#define CISREG_IOBASE_0 0x0a +#define CISREG_IOBASE_1 0x0c +#define CISREG_IOBASE_2 0x0e +#define CISREG_IOBASE_3 0x10 +#define CISREG_IOSIZE 0x12 + +/* + * Configuration Option Register + */ +#define COR_CONFIG_MASK 0x3f +#define COR_MFC_CONFIG_MASK 0x38 +#define COR_FUNC_ENA 0x01 +#define COR_ADDR_DECODE 0x02 +#define COR_IREQ_ENA 0x04 +#define COR_LEVEL_REQ 0x40 +#define COR_SOFT_RESET 0x80 + +/* + * Card Configuration and Status Register + */ +#define CCSR_INTR_ACK 0x01 +#define CCSR_INTR_PENDING 0x02 +#define CCSR_POWER_DOWN 0x04 +#define CCSR_AUDIO_ENA 0x08 +#define CCSR_IOIS8 0x20 +#define CCSR_SIGCHG_ENA 0x40 +#define CCSR_CHANGED 0x80 + +/* + * Pin Replacement Register + */ +#define PRR_WP_STATUS 0x01 +#define PRR_READY_STATUS 0x02 +#define PRR_BVD2_STATUS 0x04 +#define PRR_BVD1_STATUS 0x08 +#define PRR_WP_EVENT 0x10 +#define PRR_READY_EVENT 0x20 +#define PRR_BVD2_EVENT 0x40 +#define PRR_BVD1_EVENT 0x80 + +/* + * Socket and Copy Register + */ +#define SCR_SOCKET_NUM 0x0f +#define SCR_COPY_NUM 0x70 + +/* + * Extended Status Register + */ +#define ESR_REQ_ATTN_ENA 0x01 +#define ESR_REQ_ATTN 0x10 + +/* + * CardBus Function Status Registers + */ +#define CBFN_EVENT 0x00 +#define CBFN_MASK 0x04 +#define CBFN_STATE 0x08 +#define CBFN_FORCE 0x0c + +/* + * These apply to all the CardBus function registers + */ +#define CBFN_WP 0x0001 +#define CBFN_READY 0x0002 +#define CBFN_BVD2 0x0004 +#define CBFN_BVD1 0x0008 +#define CBFN_GWAKE 0x0010 +#define CBFN_INTR 0x8000 + +/* + * Extra bits in the Function Event Mask Register + */ +#define FEMR_BAM_ENA 0x0020 +#define FEMR_PWM_ENA 0x0040 +#define FEMR_WKUP_MASK 0x4000 + +#endif /* _LINUX_CISREG_H */ diff --git a/klaptopdaemon/linux/cistpl.h b/klaptopdaemon/linux/cistpl.h new file mode 100644 index 0000000..8fee55b --- /dev/null +++ b/klaptopdaemon/linux/cistpl.h @@ -0,0 +1,543 @@ +/* + * cistpl.h 1.27 1998/09/30 18:08:46 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISTPL_H +#define _LINUX_CISTPL_H + +#define CISTPL_NULL 0x00 +#define CISTPL_DEVICE 0x01 +#define CISTPL_LONGLINK_CB 0x02 +#define CISTPL_CONFIG_CB 0x04 +#define CISTPL_CFTABLE_ENTRY_CB 0x05 +#define CISTPL_LONGLINK_MFC 0x06 +#define CISTPL_BAR 0x07 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_LONGLINK_A 0x11 +#define CISTPL_LONGLINK_C 0x12 +#define CISTPL_LINKTARGET 0x13 +#define CISTPL_NO_LINK 0x14 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_DEVICE_A 0x17 +#define CISTPL_JEDEC_C 0x18 +#define CISTPL_JEDEC_A 0x19 +#define CISTPL_CONFIG 0x1a +#define CISTPL_CFTABLE_ENTRY 0x1b +#define CISTPL_DEVICE_OC 0x1c +#define CISTPL_DEVICE_OA 0x1d +#define CISTPL_DEVICE_GEO 0x1e +#define CISTPL_DEVICE_GEO_A 0x1f +#define CISTPL_MANFID 0x20 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SWIL 0x23 +#define CISTPL_END 0xff +/* Layer 2 tuples */ +#define CISTPL_VERS_2 0x40 +#define CISTPL_FORMAT 0x41 +#define CISTPL_GEOMETRY 0x42 +#define CISTPL_BYTEORDER 0x43 +#define CISTPL_DATE 0x44 +#define CISTPL_BATTERY 0x45 +/* Layer 3 tuples */ +#define CISTPL_ORG 0x46 + +typedef struct cistpl_longlink_t { + u_int addr; +} cistpl_longlink_t; + +typedef struct cistpl_checksum_t { + u_short addr; + u_short len; + u_char sum; +} cistpl_checksum_t; + +#define CISTPL_MAX_FUNCTIONS 8 +#define CISTPL_MFC_ATTR 0x00 +#define CISTPL_MFC_COMMON 0x01 + +typedef struct cistpl_longlink_mfc_t { + u_char nfn; + struct { + u_char space; + u_int addr; + } fn[CISTPL_MAX_FUNCTIONS]; +} cistpl_longlink_mfc_t; + +#define CISTPL_MAX_ALTSTR_STRINGS 4 + +typedef struct cistpl_altstr_t { + u_char ns; + u_char ofs[CISTPL_MAX_ALTSTR_STRINGS]; + char str[254]; +} cistpl_altstr_t; + +#define CISTPL_DTYPE_NULL 0x00 +#define CISTPL_DTYPE_ROM 0x01 +#define CISTPL_DTYPE_OTPROM 0x02 +#define CISTPL_DTYPE_EPROM 0x03 +#define CISTPL_DTYPE_EEPROM 0x04 +#define CISTPL_DTYPE_FLASH 0x05 +#define CISTPL_DTYPE_SRAM 0x06 +#define CISTPL_DTYPE_DRAM 0x07 +#define CISTPL_DTYPE_FUNCSPEC 0x0d +#define CISTPL_DTYPE_EXTEND 0x0e + +#define CISTPL_MAX_DEVICES 4 + +typedef struct cistpl_device_t { + u_char ndev; + struct { + u_char type; + u_char wp; + u_int speed; + u_int size; + } dev[CISTPL_MAX_DEVICES]; +} cistpl_device_t; + +#define CISTPL_DEVICE_MWAIT 0x01 +#define CISTPL_DEVICE_3VCC 0x02 + +typedef struct cistpl_device_o_t { + u_char flags; + cistpl_device_t device; +} cistpl_device_o_t; + +#define CISTPL_VERS_1_MAX_PROD_STRINGS 4 + +typedef struct cistpl_vers_1_t { + u_char major; + u_char minor; + u_char ns; + u_char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS]; + char str[254]; +} cistpl_vers_1_t; + +typedef struct cistpl_jedec_t { + u_char nid; + struct { + u_char mfr; + u_char info; + } id[CISTPL_MAX_DEVICES]; +} cistpl_jedec_t; + +typedef struct cistpl_manfid_t { + u_short manf; + u_short card; +} cistpl_manfid_t; + +#define CISTPL_FUNCID_MULTI 0x00 +#define CISTPL_FUNCID_MEMORY 0x01 +#define CISTPL_FUNCID_SERIAL 0x02 +#define CISTPL_FUNCID_PARALLEL 0x03 +#define CISTPL_FUNCID_FIXED 0x04 +#define CISTPL_FUNCID_VIDEO 0x05 +#define CISTPL_FUNCID_NETWORK 0x06 +#define CISTPL_FUNCID_AIMS 0x07 +#define CISTPL_FUNCID_SCSI 0x08 + +#define CISTPL_SYSINIT_POST 0x01 +#define CISTPL_SYSINIT_ROM 0x02 + +typedef struct cistpl_funcid_t { + u_char func; + u_char sysinit; +} cistpl_funcid_t; + +typedef struct cistpl_funce_t { + u_char type; + u_char data[1]; +} cistpl_funce_t; + +/*====================================================================== + + Modem Function Extension Tuples + +======================================================================*/ + +#define CISTPL_FUNCE_SERIAL 0x00 +#define CISTPL_FUNCE_SERIAL_DATA 0x08 +#define CISTPL_FUNCE_SERIAL_FAX 0x09 +#define CISTPL_FUNCE_SERIAL_VOICE 0x0a +#define CISTPL_FUNCE_CAP 0x01 +#define CISTPL_FUNCE_CAP_DATA 0x05 +#define CISTPL_FUNCE_CAP_FAX 0x06 +#define CISTPL_FUNCE_CAP_VOICE 0x07 +#define CISTPL_FUNCE_SERV_DATA 0x02 +#define CISTPL_FUNCE_SERV_FAX_1 0x13 +#define CISTPL_FUNCE_SERV_FAX_2 0x23 +#define CISTPL_FUNCE_SERV_FAX_3 0x33 +#define CISTPL_FUNCE_SERV_VOICE 0x84 + +/* UART identification */ +#define CISTPL_SERIAL_UART_8250 0x00 +#define CISTPL_SERIAL_UART_16450 0x01 +#define CISTPL_SERIAL_UART_16550 0x02 + +/* UART capabilities */ +#define CISTPL_SERIAL_UART_SPACE 0x01 +#define CISTPL_SERIAL_UART_MARK 0x02 +#define CISTPL_SERIAL_UART_ODD 0x04 +#define CISTPL_SERIAL_UART_EVEN 0x08 +#define CISTPL_SERIAL_UART_5BIT 0x01 +#define CISTPL_SERIAL_UART_6BIT 0x02 +#define CISTPL_SERIAL_UART_7BIT 0x04 +#define CISTPL_SERIAL_UART_8BIT 0x08 +#define CISTPL_SERIAL_UART_1STOP 0x10 +#define CISTPL_SERIAL_UART_MSTOP 0x20 +#define CISTPL_SERIAL_UART_2STOP 0x40 + +typedef struct cistpl_serial_t { + u_char uart_type; + u_char uart_cap_0; + u_char uart_cap_1; +} cistpl_serial_t; + +typedef struct cistpl_modem_cap_t { + u_char flow; + u_char cmd_buf; + u_int rcv_buf:24; + u_int xmit_buf:24; +} cistpl_modem_cap_t; + +typedef struct cistpl_data_serv_t { + u_char max_data_0; + u_char max_data_1; + u_char modulation_0; + u_char modulation_1; + u_char error_control; + u_char compression; + u_char cmd_protocol; + u_char escape; + u_char encrypt; + u_char misc_features; + u_char ccitt_code[1]; +} cistpl_data_serv_t; + +typedef struct cistpl_fax_serv_t { + u_char max_data_0; + u_char max_data_1; + u_char modulation; + u_char encrypt; + u_char features_0; + u_char features_1; + u_char ccitt_code[1]; +} cistpl_fax_serv_t; + +typedef struct cistpl_voice_serv_t { + u_char max_data_0; + u_char max_data_1; +} cistpl_voice_serv_t; + +/*====================================================================== + + LAN Function Extension Tuples + +======================================================================*/ + +#define CISTPL_FUNCE_LAN_TECH 0x01 +#define CISTPL_FUNCE_LAN_SPEED 0x02 +#define CISTPL_FUNCE_LAN_MEDIA 0x03 +#define CISTPL_FUNCE_LAN_NODE_ID 0x04 +#define CISTPL_FUNCE_LAN_CONNECTOR 0x05 + +/* LAN technologies */ +#define CISTPL_LAN_TECH_ARCNET 0x01 +#define CISTPL_LAN_TECH_ETHERNET 0x02 +#define CISTPL_LAN_TECH_TOKENRING 0x03 +#define CISTPL_LAN_TECH_LOCALTALK 0x04 +#define CISTPL_LAN_TECH_FDDI 0x05 +#define CISTPL_LAN_TECH_ATM 0x06 +#define CISTPL_LAN_TECH_WIRELESS 0x07 + +typedef struct cistpl_lan_tech_t { + u_char tech; +} cistpl_lan_tech_t; + +typedef struct cistpl_lan_speed_t { + u_int speed; +} cistpl_lan_speed_t; + +/* LAN media definitions */ +#define CISTPL_LAN_MEDIA_UTP 0x01 +#define CISTPL_LAN_MEDIA_STP 0x02 +#define CISTPL_LAN_MEDIA_THIN_COAX 0x03 +#define CISTPL_LAN_MEDIA_THICK_COAX 0x04 +#define CISTPL_LAN_MEDIA_FIBER 0x05 +#define CISTPL_LAN_MEDIA_900MHZ 0x06 +#define CISTPL_LAN_MEDIA_2GHZ 0x07 +#define CISTPL_LAN_MEDIA_5GHZ 0x08 +#define CISTPL_LAN_MEDIA_DIFF_IR 0x09 +#define CISTPL_LAN_MEDIA_PTP_IR 0x0a + +typedef struct cistpl_lan_media_t { + u_char media; +} cistpl_lan_media_t; + +typedef struct cistpl_lan_node_id_t { + u_char nb; + u_char id[16]; +} cistpl_lan_node_id_t; + +typedef struct cistpl_lan_connector_t { + u_char code; +} cistpl_lan_connector_t; + +/*====================================================================== + + IDE Function Extension Tuples + +======================================================================*/ + +#define CISTPL_IDE_INTERFACE 0x01 + +typedef struct cistpl_ide_interface_t { + u_char interface; +} cistpl_ide_interface_t; + +/* First feature byte */ +#define CISTPL_IDE_SILICON 0x04 +#define CISTPL_IDE_UNIQUE 0x08 +#define CISTPL_IDE_DUAL 0x10 + +/* Second feature byte */ +#define CISTPL_IDE_HAS_SLEEP 0x01 +#define CISTPL_IDE_HAS_STANDBY 0x02 +#define CISTPL_IDE_HAS_IDLE 0x04 +#define CISTPL_IDE_LOW_POWER 0x08 +#define CISTPL_IDE_REG_INHIBIT 0x10 +#define CISTPL_IDE_HAS_INDEX 0x20 +#define CISTPL_IDE_IOIS16 0x40 + +typedef struct cistpl_ide_feature_t { + u_char feature1; + u_char feature2; +} cistpl_ide_feature_t; + +#define CISTPL_FUNCE_IDE_IFACE 0x01 +#define CISTPL_FUNCE_IDE_MASTER 0x02 +#define CISTPL_FUNCE_IDE_SLAVE 0x03 + +/*====================================================================== + + Configuration Table Entries + +======================================================================*/ + +#define CISTPL_BAR_SPACE 0x07 +#define CISTPL_BAR_SPACE_IO 0x10 +#define CISTPL_BAR_PREFETCH 0x20 +#define CISTPL_BAR_CACHEABLE 0x40 +#define CISTPL_BAR_1MEG_MAP 0x80 + +typedef struct cistpl_bar_t { + u_char attr; + u_int size; +} cistpl_bar_t; + +typedef struct cistpl_config_t { + u_char last_idx; + u_int base; + u_int rmask[4]; + u_char subtuples; +} cistpl_config_t; + +/* These are bits in the 'present' field, and indices in 'param' */ +#define CISTPL_POWER_VNOM 0 +#define CISTPL_POWER_VMIN 1 +#define CISTPL_POWER_VMAX 2 +#define CISTPL_POWER_ISTATIC 3 +#define CISTPL_POWER_IAVG 4 +#define CISTPL_POWER_IPEAK 5 +#define CISTPL_POWER_IDOWN 6 + +#define CISTPL_POWER_HIGHZ_OK 0x01 +#define CISTPL_POWER_HIGHZ_REQ 0x02 + +typedef struct cistpl_power_t { + u_char present; + u_char flags; + u_int param[7]; +} cistpl_power_t; + +typedef struct cistpl_timing_t { + u_int wait, waitscale; + u_int ready, rdyscale; + u_int reserved, rsvscale; +} cistpl_timing_t; + +#define CISTPL_IO_LINES_MASK 0x1f +#define CISTPL_IO_8BIT 0x20 +#define CISTPL_IO_16BIT 0x40 +#define CISTPL_IO_RANGE 0x80 + +#define CISTPL_IO_MAX_WIN 16 + +typedef struct cistpl_io_t { + u_char flags; + u_char nwin; + struct { + u_int base; + u_int len; + } win[CISTPL_IO_MAX_WIN]; +} cistpl_io_t; + +typedef struct cistpl_irq_t { + u_int IRQInfo1; + u_int IRQInfo2; +} cistpl_irq_t; + +#define CISTPL_MEM_MAX_WIN 8 + +typedef struct cistpl_mem_t { + u_char flags; + u_char nwin; + struct { + u_int len; + u_int card_addr; + u_int host_addr; + } win[CISTPL_MEM_MAX_WIN]; +} cistpl_mem_t; + +#define CISTPL_CFTABLE_DEFAULT 0x0001 +#define CISTPL_CFTABLE_BVDS 0x0002 +#define CISTPL_CFTABLE_WP 0x0004 +#define CISTPL_CFTABLE_RDYBSY 0x0008 +#define CISTPL_CFTABLE_MWAIT 0x0010 +#define CISTPL_CFTABLE_AUDIO 0x0800 +#define CISTPL_CFTABLE_READONLY 0x1000 +#define CISTPL_CFTABLE_PWRDOWN 0x2000 + +typedef struct cistpl_cftable_entry_t { + u_char index; + u_short flags; + u_char interface; + cistpl_power_t vcc, vpp1, vpp2; + cistpl_timing_t timing; + cistpl_io_t io; + cistpl_irq_t irq; + cistpl_mem_t mem; + u_char subtuples; +} cistpl_cftable_entry_t; + +#define CISTPL_CFTABLE_MASTER 0x000100 +#define CISTPL_CFTABLE_INVALIDATE 0x000200 +#define CISTPL_CFTABLE_VGA_PALETTE 0x000400 +#define CISTPL_CFTABLE_PARITY 0x000800 +#define CISTPL_CFTABLE_WAIT 0x001000 +#define CISTPL_CFTABLE_SERR 0x002000 +#define CISTPL_CFTABLE_FAST_BACK 0x004000 +#define CISTPL_CFTABLE_BINARY_AUDIO 0x010000 +#define CISTPL_CFTABLE_PWM_AUDIO 0x020000 + +typedef struct cistpl_cftable_entry_cb_t { + u_char index; + u_int flags; + cistpl_power_t vcc, vpp1, vpp2; + u_char io; + cistpl_irq_t irq; + u_char mem; + u_char subtuples; +} cistpl_cftable_entry_cb_t; + +typedef struct cistpl_device_geo_t { + u_char ngeo; + struct { + u_char buswidth; + u_int erase_block; + u_int read_block; + u_int write_block; + u_int partition; + u_int interleave; + } geo[CISTPL_MAX_DEVICES]; +} cistpl_device_geo_t; + +typedef struct cistpl_vers_2_t { + u_char vers; + u_char comply; + u_short dindex; + u_char vspec8, vspec9; + u_char nhdr; + u_char vendor, info; + char str[244]; +} cistpl_vers_2_t; + +typedef struct cistpl_org_t { + u_char data_org; + char desc[30]; +} cistpl_org_t; + +#define CISTPL_ORG_FS 0x00 +#define CISTPL_ORG_APPSPEC 0x01 +#define CISTPL_ORG_XIP 0x02 + +typedef union cisparse_t { + cistpl_device_t device; + cistpl_checksum_t checksum; + cistpl_longlink_t longlink; + cistpl_longlink_mfc_t longlink_mfc; + cistpl_vers_1_t version_1; + cistpl_altstr_t altstr; + cistpl_jedec_t jedec; + cistpl_manfid_t manfid; + cistpl_funcid_t funcid; + cistpl_funce_t funce; + cistpl_bar_t bar; + cistpl_config_t config; + cistpl_cftable_entry_t cftable_entry; + cistpl_cftable_entry_cb_t cftable_entry_cb; + cistpl_device_geo_t device_geo; + cistpl_vers_2_t vers_2; + cistpl_org_t org; +} cisparse_t; + +typedef struct tuple_t { + u_int Attributes; + cisdata_t DesiredTuple; + u_int Flags; /* internal use */ + u_int LinkOffset; /* internal use */ + u_int CISOffset; /* internal use */ + cisdata_t TupleCode; + cisdata_t TupleLink; + cisdata_t TupleOffset; + cisdata_t TupleDataMax; + cisdata_t TupleDataLen; + cisdata_t *TupleData; +} tuple_t; + +/* Special cisdata_t value */ +#define RETURN_FIRST_TUPLE 0xff + +/* Attributes for tuple calls */ +#define TUPLE_RETURN_LINK 0x01 +#define TUPLE_RETURN_COMMON 0x02 + +/* For ValidateCIS */ +typedef struct cisinfo_t { + u_int Chains; +} cisinfo_t; + +#define CISTPL_MAX_CIS_SIZE 0x200 + +/* For ReplaceCIS */ +typedef struct cisdump_t { + u_int Length; + cisdata_t Data[CISTPL_MAX_CIS_SIZE]; +} cisdump_t; + +#endif /* LINUX_CISTPL_H */ diff --git a/klaptopdaemon/linux/cs.h b/klaptopdaemon/linux/cs.h new file mode 100644 index 0000000..b8610ca --- /dev/null +++ b/klaptopdaemon/linux/cs.h @@ -0,0 +1,455 @@ +/* + * cs.h 1.63 1998/12/09 07:36:24 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CS_H +#define _LINUX_CS_H + +/* For AccessConfigurationRegister */ +typedef struct conf_reg_t { + u_char Function; + u_int Action; + off_t Offset; + u_int Value; +} conf_reg_t; + +/* Actions */ +#define CS_READ 1 +#define CS_WRITE 2 + +/* for AdjustResourceInfo */ +typedef struct adjust_t { + u_int Action; + u_int Resource; + u_int Attributes; + union { + struct memory { + u_long Base; + u_long Size; + } memory; + struct io { + ioaddr_t BasePort; + ioaddr_t NumPorts; + u_int IOAddrLines; + } io; + struct irq { + u_int IRQ; + } irq; + } resource; +} adjust_t; + +/* Action field */ +#define REMOVE_MANAGED_RESOURCE 1 +#define ADD_MANAGED_RESOURCE 2 +#define GET_FIRST_MANAGED_RESOURCE 3 +#define GET_NEXT_MANAGED_RESOURCE 4 +/* Resource field */ +#define RES_MEMORY_RANGE 1 +#define RES_IO_RANGE 2 +#define RES_IRQ 3 +/* Attribute field */ +#define RES_IRQ_TYPE 0x03 +#define RES_IRQ_TYPE_EXCLUSIVE 0 +#define RES_IRQ_TYPE_TIME 1 +#define RES_IRQ_TYPE_DYNAMIC 2 +#define RES_IRQ_CSC 0x04 +#define RES_SHARED 0x08 +#define RES_RESERVED 0x10 +#define RES_ALLOCATED 0x20 +#define RES_REMOVED 0x40 + +typedef struct servinfo_t { + char Signature[2]; + u_int Count; + u_int Revision; + u_int CSLevel; + char *VendorString; +} servinfo_t; + +typedef struct event_callback_args_t { + client_handle_t client_handle; + void *info; + void *mtdrequest; + void *buffer; + void *misc; + void *client_data; +} event_callback_args_t; + +/* for GetConfigurationInfo */ +typedef struct config_info_t { + u_char Function; + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; + u_int IntType; + u_int ConfigBase; + u_char Status, Pin, Copy, Option, ExtStatus; + u_int Present; + u_int CardValues; + u_int AssignedIRQ; + u_int IRQAttributes; + ioaddr_t BasePort1; + ioaddr_t NumPorts1; + u_int Attributes1; + ioaddr_t BasePort2; + ioaddr_t NumPorts2; + u_int Attributes2; + u_int IOAddrLines; +} config_info_t; + +/* For CardValues field */ +#define CV_OPTION_VALUE 0x01 +#define CV_STATUS_VALUE 0x02 +#define CV_PIN_REPLACEMENT 0x04 +#define CV_COPY_VALUE 0x08 +#define CV_EXT_STATUS 0x10 + +/* For GetFirst/NextClient */ +typedef struct client_req_t { + socket_t Socket; + u_int Attributes; +} client_req_t; + +#define CLIENT_THIS_SOCKET 0x01 + +/* For RegisterClient */ +typedef struct client_reg_t { + dev_info_t *dev_info; + u_int Attributes; + u_int EventMask; + int (*event_handler)(event_t event, int priority, + event_callback_args_t *); + event_callback_args_t event_callback_args; + u_int Version; +} client_reg_t; + +/* ModifyConfiguration */ +typedef struct modconf_t { + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; +} modconf_t; + +/* Attributes for ModifyConfiguration */ +#define CONF_IRQ_CHANGE_VALID 0x100 +#define CONF_VCC_CHANGE_VALID 0x200 +#define CONF_VPP1_CHANGE_VALID 0x400 +#define CONF_VPP2_CHANGE_VALID 0x800 + +/* For RequestConfiguration */ +typedef struct config_req_t { + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; + u_int IntType; + u_int ConfigBase; + u_char Status, Pin, Copy, ExtStatus; + u_char ConfigIndex; + u_int Present; +} config_req_t; + +/* Attributes for RequestConfiguration */ +#define CONF_ENABLE_IRQ 0x01 +#define CONF_ENABLE_DMA 0x02 +#define CONF_ENABLE_SPKR 0x04 +#define CONF_VALID_CLIENT 0x100 + +/* IntType field */ +#define INT_MEMORY 0x01 +#define INT_MEMORY_AND_IO 0x02 +#define INT_CARDBUS 0x04 + +/* For RequestIO and ReleaseIO */ +typedef struct io_req_t { + ioaddr_t BasePort1; + ioaddr_t NumPorts1; + u_int Attributes1; + ioaddr_t BasePort2; + ioaddr_t NumPorts2; + u_int Attributes2; + u_int IOAddrLines; +} io_req_t; + +/* Attributes for RequestIO and ReleaseIO */ +#define IO_SHARED 0x01 +#define IO_FIRST_SHARED 0x02 +#define IO_FORCE_ALIAS_ACCESS 0x04 +#define IO_DATA_PATH_WIDTH 0x18 +#define IO_DATA_PATH_WIDTH_8 0x00 +#define IO_DATA_PATH_WIDTH_16 0x08 +#define IO_DATA_PATH_WIDTH_AUTO 0x10 + +/* For RequestIRQ and ReleaseIRQ */ +typedef struct irq_req_t { + u_int Attributes; + u_int AssignedIRQ; + u_int IRQInfo1, IRQInfo2; + void *Handler; + void *Instance; +} irq_req_t; + +/* Attributes for RequestIRQ and ReleaseIRQ */ +#define IRQ_TYPE 0x03 +#define IRQ_TYPE_EXCLUSIVE 0x00 +#define IRQ_TYPE_TIME 0x01 +#define IRQ_TYPE_DYNAMIC_SHARING 0x02 +#define IRQ_FORCED_PULSE 0x04 +#define IRQ_FIRST_SHARED 0x08 +#define IRQ_HANDLE_PRESENT 0x10 +#define IRQ_PULSE_ALLOCATED 0x100 + +/* Bits in IRQInfo1 field */ +#define IRQ_MASK 0x0f +#define IRQ_NMI_ID 0x01 +#define IRQ_IOCK_ID 0x02 +#define IRQ_BERR_ID 0x04 +#define IRQ_VEND_ID 0x08 +#define IRQ_INFO2_VALID 0x10 +#define IRQ_LEVEL_ID 0x20 +#define IRQ_PULSE_ID 0x40 +#define IRQ_SHARE_ID 0x80 + +typedef struct eventmask_t { + u_int Attributes; + u_int EventMask; +} eventmask_t; + +#define CONF_EVENT_MASK_VALID 0x01 + +/* Configuration registers present */ +#define PRESENT_OPTION 0x001 +#define PRESENT_STATUS 0x002 +#define PRESENT_PIN_REPLACE 0x004 +#define PRESENT_COPY 0x008 +#define PRESENT_EXT_STATUS 0x010 +#define PRESENT_IOBASE_0 0x020 +#define PRESENT_IOBASE_1 0x040 +#define PRESENT_IOBASE_2 0x080 +#define PRESENT_IOBASE_3 0x100 +#define PRESENT_IOSIZE 0x200 + +/* Attributes for Request/GetConfiguration */ +#define CONF_ENABLE_IRQ 0x01 +#define EXCLUSIVE_USE 0x02 +#define VALID_CLIENT 0x04 + +/* For MapMemPage */ +typedef struct memreq_t { + u_int CardOffset; + page_t Page; +} memreq_t; + +/* For ModifyWindow */ +typedef struct modwin_t { + u_int Attributes; + u_int AccessSpeed; +} modwin_t; + +/* For RequestWindow */ +typedef struct win_req_t { + u_int Attributes; + u_long Base; + u_int Size; + u_int AccessSpeed; +} win_req_t; + +/* Attributes for RequestWindow */ +#define WIN_ADDR_SPACE 0x0001 +#define WIN_ADDR_SPACE_MEM 0x0000 +#define WIN_ADDR_SPACE_IO 0x0001 +#define WIN_MEMORY_TYPE 0x0002 +#define WIN_MEMORY_TYPE_CM 0x0000 +#define WIN_MEMORY_TYPE_AM 0x0002 +#define WIN_ENABLE 0x0004 +#define WIN_DATA_WIDTH 0x0018 +#define WIN_DATA_WIDTH_8 0x0000 +#define WIN_DATA_WIDTH_16 0x0008 +#define WIN_DATA_WIDTH_32 0x0010 +#define WIN_PAGED 0x0020 +#define WIN_SHARED 0x0040 +#define WIN_FIRST_SHARED 0x0080 +#define WIN_USE_WAIT 0x0100 +#define WIN_MAP_BELOW_1MB 0x0400 +#define WIN_PREFETCH 0x0800 +#define WIN_CACHEABLE 0x1000 +#define WIN_BAR_MASK 0xe000 +#define WIN_BAR_SHIFT 13 + +/* Attributes for RegisterClient */ +#define INFO_MASTER_CLIENT 0x01 +#define INFO_IO_CLIENT 0x02 +#define INFO_MTD_CLIENT 0x04 +#define INFO_MEM_CLIENT 0x08 +#define MAX_NUM_CLIENTS 3 + +#define INFO_CARD_SHARE 0x10 +#define INFO_CARD_EXCL 0x20 + +typedef struct cs_status_t { + u_char Function; + event_t CardState; + event_t SocketState; +} cs_status_t; + +typedef struct error_info_t { + int func; + int retcode; +} error_info_t; + +/* Special stuff for binding drivers to sockets */ +typedef struct bind_req_t { + socket_t Socket; + u_char Function; + dev_info_t *dev_info; +} bind_req_t; + +/* Flag to bind to all functions */ +#define BIND_FN_ALL 0xff + +typedef struct mtd_bind_t { + socket_t Socket; + u_int Attributes; + u_int CardOffset; + dev_info_t *dev_info; +} mtd_bind_t; + +/* Events */ +#define CS_EVENT_PRI_LOW 0 +#define CS_EVENT_PRI_HIGH 1 + +#define CS_EVENT_WRITE_PROTECT 0x000001 +#define CS_EVENT_CARD_LOCK 0x000002 +#define CS_EVENT_CARD_INSERTION 0x000004 +#define CS_EVENT_CARD_REMOVAL 0x000008 +#define CS_EVENT_BATTERY_DEAD 0x000010 +#define CS_EVENT_BATTERY_LOW 0x000020 +#define CS_EVENT_READY_CHANGE 0x000040 +#define CS_EVENT_CARD_DETECT 0x000080 +#define CS_EVENT_RESET_REQUEST 0x000100 +#define CS_EVENT_RESET_PHYSICAL 0x000200 +#define CS_EVENT_CARD_RESET 0x000400 +#define CS_EVENT_REGISTRATION_COMPLETE 0x000800 +#define CS_EVENT_RESET_COMPLETE 0x001000 +#define CS_EVENT_PM_SUSPEND 0x002000 +#define CS_EVENT_PM_RESUME 0x004000 +#define CS_EVENT_INSERTION_REQUEST 0x008000 +#define CS_EVENT_EJECTION_REQUEST 0x010000 +#define CS_EVENT_MTD_REQUEST 0x020000 +#define CS_EVENT_ERASE_COMPLETE 0x040000 +#define CS_EVENT_REQUEST_ATTENTION 0x080000 +#define CS_EVENT_CB_DETECT 0x100000 +#define CS_EVENT_3VCARD 0x200000 +#define CS_EVENT_XVCARD 0x400000 + +/* Return codes */ +#define CS_SUCCESS 0x00 +#define CS_BAD_ADAPTER 0x01 +#define CS_BAD_ATTRIBUTE 0x02 +#define CS_BAD_BASE 0x03 +#define CS_BAD_EDC 0x04 +#define CS_BAD_IRQ 0x06 +#define CS_BAD_OFFSET 0x07 +#define CS_BAD_PAGE 0x08 +#define CS_READ_FAILURE 0x09 +#define CS_BAD_SIZE 0x0a +#define CS_BAD_SOCKET 0x0b +#define CS_BAD_TYPE 0x0d +#define CS_BAD_VCC 0x0e +#define CS_BAD_VPP 0x0f +#define CS_BAD_WINDOW 0x11 +#define CS_WRITE_FAILURE 0x12 +#define CS_NO_CARD 0x14 +#define CS_UNSUPPORTED_FUNCTION 0x15 +#define CS_UNSUPPORTED_MODE 0x16 +#define CS_BAD_SPEED 0x17 +#define CS_BUSY 0x18 +#define CS_GENERAL_FAILURE 0x19 +#define CS_WRITE_PROTECTED 0x1a +#define CS_BAD_ARG_LENGTH 0x1b +#define CS_BAD_ARGS 0x1c +#define CS_CONFIGURATION_LOCKED 0x1d +#define CS_IN_USE 0x1e +#define CS_NO_MORE_ITEMS 0x1f +#define CS_OUT_OF_RESOURCE 0x20 +#define CS_BAD_HANDLE 0x21 + +#define CS_BAD_TUPLE 0x40 + +#ifdef __KERNEL__ + +/* + * Calls to set up low-level "Socket Services" drivers + */ + +typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg); +extern int register_ss_entry(int nsock, ss_entry_t entry); +extern void unregister_ss_entry(ss_entry_t entry); + +/* + * The main Card Services entry point + */ + +enum service { + AccessConfigurationRegister, AddSocketServices, + AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory, + DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo, + GetClientInfo, GetConfigurationInfo, GetEventMask, + GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple, + GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple, + GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage, + MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow, + OpenMemory, ParseTuple, ReadMemory, RegisterClient, + RegisterEraseQueue, RegisterMTD, RegisterTimer, + ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ, + ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices, + RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ, + RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry, + SetEventMask, SetRegion, ValidateCIS, VendorSpecific, + WriteMemory, BindDevice, BindMTD, ReportError, + SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS +}; + +#ifdef IN_CARD_SERVICES +extern int CardServices(int func, void *a1, void *a2, void *a3); +#else +extern int CardServices(int func, ...); +#endif + +#ifdef __BEOS__ +#define SS_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define MTD_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define CS_CLIENT_MODULE_NAME "bus_managers/pcmcia_cs/client/v1" +typedef struct cs_client_module_info { + bus_manager_info binfo; + int (*_CardServices)(int, ...); + int (*_MTDHelperEntry)(int, ...); + void (*_add_timer)(struct timer_list *); + void (*_del_timer)(struct timer_list *); +} cs_client_module_info; +#define CS_SOCKET_MODULE_NAME "bus_managers/pcmcia_cs/socket/v1" +typedef struct cs_socket_module_info { + bus_manager_info binfo; + int (*_register_ss_entry)(int, ss_entry_t); + void (*_unregister_ss_entry)(ss_entry_t); + void (*_add_timer)(struct timer_list *); + void (*_del_timer)(struct timer_list *); + int (*register_resource)(int, u_long, u_long); + int (*release_resource)(int, u_long, u_long); + int (*check_resource)(int, u_long, u_long); +} cs_socket_module_info; +#endif + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_CS_H */ diff --git a/klaptopdaemon/linux/cs_types.h b/klaptopdaemon/linux/cs_types.h new file mode 100644 index 0000000..8f9df45 --- /dev/null +++ b/klaptopdaemon/linux/cs_types.h @@ -0,0 +1,50 @@ +/* + * cs_types.h 1.13 1998/07/14 00:52:20 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CS_TYPES_H +#define _LINUX_CS_TYPES_H + +#ifdef __linux__ +#include <linux/types.h> +#endif + +typedef u_short socket_t; +typedef u_short ioaddr_t; +typedef u_int event_t; +typedef u_char cisdata_t; +typedef u_short page_t; + +struct client_t; +typedef struct client_t *client_handle_t; + +struct window_t; +typedef struct window_t *window_handle_t; + +struct region_t; +typedef struct region_t *memory_handle_t; + +struct eraseq_t; +typedef struct eraseq_t *eraseq_handle_t; + +#ifndef DEV_NAME_LEN +#define DEV_NAME_LEN 32 +#endif + +typedef char dev_info_t[DEV_NAME_LEN]; + +#endif /* _LINUX_CS_TYPES_H */ diff --git a/klaptopdaemon/linux/driver_ops.h b/klaptopdaemon/linux/driver_ops.h new file mode 100644 index 0000000..a6a71ee --- /dev/null +++ b/klaptopdaemon/linux/driver_ops.h @@ -0,0 +1,71 @@ +/* + * driver_ops.h 1.11 1998/11/18 07:01:50 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_DRIVER_OPS_H +#define _LINUX_DRIVER_OPS_H + +#ifndef DEV_NAME_LEN +#define DEV_NAME_LEN 32 +#endif + +#ifdef __KERNEL__ + +typedef struct dev_node_t { + char dev_name[DEV_NAME_LEN]; + u_short major, minor; + struct dev_node_t *next; +} dev_node_t; + +typedef struct dev_locator_t { + enum { LOC_ISA, LOC_PCI } bus; + union { + struct { + u_short io_base_1, io_base_2; + u_long mem_base; + u_char irq, dma; + } isa; + struct { + u_char bus; + u_char devfn; + } pci; + } b; +} dev_locator_t; + +typedef struct driver_operations { + char *name; + dev_node_t *(*attach) (dev_locator_t *loc); + void (*suspend) (dev_node_t *dev); + void (*resume) (dev_node_t *dev); + void (*detach) (dev_node_t *dev); +} driver_operations; + +int register_driver(struct driver_operations *ops); +void unregister_driver(struct driver_operations *ops); + +#ifdef __BEOS__ +#define CB_ENABLER_MODULE_NAME "bus_managers/cb_enabler/v1" +typedef struct cb_enabler_module_info { + bus_manager_info binfo; + int (*register_driver)(struct driver_operations *ops); + void (*unregister_driver)(struct driver_operations *ops); +} cb_enabler_module_info; +#endif /* __BEOS__ */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_DRIVER_OPS_H */ diff --git a/klaptopdaemon/linux/ds.h b/klaptopdaemon/linux/ds.h new file mode 100644 index 0000000..11e0740 --- /dev/null +++ b/klaptopdaemon/linux/ds.h @@ -0,0 +1,142 @@ +/* + * ds.h 1.49 1998/08/03 19:12:23 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_DS_H +#define _LINUX_DS_H + +#include "driver_ops.h" +#include "bulkmem.h" + +typedef struct tuple_parse_t { + tuple_t tuple; + cisdata_t data[255]; + cisparse_t parse; +} tuple_parse_t; + +typedef struct bind_info_t { + dev_info_t dev_info; + u_char function; + struct dev_link_t *instance; + char name[DEV_NAME_LEN]; + u_short major, minor; + void *next; +} bind_info_t; + +typedef struct mtd_info_t { + dev_info_t dev_info; + u_int Attributes; + u_int CardOffset; +} mtd_info_t; + +typedef union ds_ioctl_arg_t { + servinfo_t servinfo; + adjust_t adjust; + config_info_t config; + tuple_t tuple; + tuple_parse_t tuple_parse; + client_req_t client_req; + cs_status_t status; + conf_reg_t conf_reg; + cisinfo_t cisinfo; + region_info_t region; + bind_info_t bind_info; + mtd_info_t mtd_info; + cisdump_t cisdump; +} ds_ioctl_arg_t; + +#define DS_GET_CARD_SERVICES_INFO _IOR ('d', 1, servinfo_t) +#define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t) +#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t) +#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t) +#define DS_GET_NEXT_TUPLE _IOWR('d', 5, tuple_t) +#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t) +#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t) +#define DS_RESET_CARD _IO ('d', 8) +#define DS_GET_STATUS _IOWR('d', 9, cs_status_t) +#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t) +#define DS_VALIDATE_CIS _IOR ('d', 11, cisinfo_t) +#define DS_SUSPEND_CARD _IO ('d', 12) +#define DS_RESUME_CARD _IO ('d', 13) +#define DS_EJECT_CARD _IO ('d', 14) +#define DS_INSERT_CARD _IO ('d', 15) +#define DS_GET_FIRST_REGION _IOWR('d', 16, region_info_t) +#define DS_GET_NEXT_REGION _IOWR('d', 17, region_info_t) +#define DS_REPLACE_CIS _IOWR('d', 18, cisdump_t) + +#define DS_BIND_REQUEST _IOWR('d', 60, bind_info_t) +#define DS_GET_DEVICE_INFO _IOWR('d', 61, bind_info_t) +#define DS_GET_NEXT_DEVICE _IOWR('d', 62, bind_info_t) +#define DS_UNBIND_REQUEST _IOW ('d', 63, bind_info_t) +#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t) + +#ifdef __KERNEL__ + +typedef struct dev_link_t { + dev_node_t *dev; + u_int state, open; + struct wait_queue *pending; + struct timer_list release; + client_handle_t handle; + io_req_t io; + irq_req_t irq; + config_req_t conf; + window_handle_t win; + void *priv; + struct dev_link_t *next; +} dev_link_t; + +/* Flags for device state */ +#define DEV_PRESENT 0x01 +#define DEV_CONFIG 0x02 +#define DEV_STALE_CONFIG 0x04 /* release on close */ +#define DEV_STALE_LINK 0x08 /* detach on release */ +#define DEV_CONFIG_PENDING 0x10 +#define DEV_RELEASE_PENDING 0x20 +#define DEV_SUSPEND 0x40 +#define DEV_BUSY 0x80 + +#define DEV_OK(l) \ + ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT))) + +int register_pccard_driver(dev_info_t *dev_info, + dev_link_t *(*attach)(void), + void (*detach)(dev_link_t *)); + +int unregister_pccard_driver(dev_info_t *dev_info); + +#define register_pcmcia_driver register_pccard_driver +#define unregister_pcmcia_driver unregister_pccard_driver + +#ifdef __BEOS__ +#define DS_MODULE_NAME "bus_managers/pcmcia_ds/v1" +typedef struct ds_module_info { + bus_manager_info binfo; + int (*_register_pccard_driver)(dev_info_t *, + dev_link_t *(*)(void), + void (*)(dev_link_t *)); + int (*_unregister_pccard_driver)(dev_info_t *); + struct driver_info_t **root_driver; + int *sockets; + struct socket_info_t **socket_table; + sem_id *list_sem; +} ds_module_info; +#endif /* __BEOS__ */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_DS_H */ diff --git a/klaptopdaemon/linux/ftl.h b/klaptopdaemon/linux/ftl.h new file mode 100644 index 0000000..9357d17 --- /dev/null +++ b/klaptopdaemon/linux/ftl.h @@ -0,0 +1,62 @@ +/* + * ftl.h 1.4 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_FTL_H +#define _LINUX_FTL_H + +typedef struct erase_unit_header_t { + u_char LinkTargetTuple[5]; + u_char DataOrgTuple[10]; + u_char NumTransferUnits; + u_int EraseCount; + u_short LogicalEUN; + u_char BlockSize; + u_char EraseUnitSize; + u_short FirstPhysicalEUN; + u_short NumEraseUnits; + u_int FormattedSize; + u_int FirstVMAddress; + u_short NumVMPages; + u_char Flags; + u_char Code; + u_int SerialNumber; + u_int AltEUHOffset; + u_int BAMOffset; + u_char Reserved[12]; + u_char EndTuple[2]; +} erase_unit_header_t; + +/* Flags in erase_unit_header_t */ +#define HIDDEN_AREA 0x01 +#define REVERSE_POLARITY 0x02 +#define DOUBLE_BAI 0x04 + +/* Definitions for block allocation information */ + +#define BLOCK_FREE(b) ((b) == 0xffffffff) +#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe)) + +#define BLOCK_TYPE(b) ((b) & 0x7f) +#define BLOCK_ADDRESS(b) ((b) & ~0x7f) +#define BLOCK_NUMBER(b) ((b) >> 9) +#define BLOCK_CONTROL 0x30 +#define BLOCK_DATA 0x40 +#define BLOCK_REPLACEMENT 0x60 +#define BLOCK_BAD 0x70 + +#endif /* _LINUX_FTL_H */ diff --git a/klaptopdaemon/linux/k_compat.h b/klaptopdaemon/linux/k_compat.h new file mode 100644 index 0000000..2b14312 --- /dev/null +++ b/klaptopdaemon/linux/k_compat.h @@ -0,0 +1,246 @@ +/* + * k_compat.h 1.74 1999/01/07 03:46:29 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_K_COMPAT_H +#define _LINUX_K_COMPAT_H + +#define __LINUX__ +#define VERSION(v,p,s) (((v)<<16)+(p<<8)+s) + +#define RUN_AT(x) (jiffies+(x)) +#define CONST const +#define ALLOC_SKB(len) dev_alloc_skb(len+2) +#define DEVICE(req) ((req)->rq_dev) +#define GET_PACKET(dev, skb, count) \ + skb_reserve((skb), 2); \ + BLOCK_INPUT(skb_put((skb), (count)), (count)); \ + (skb)->protocol = eth_type_trans((skb), (dev)) + +#define BLK_DEV_HDR "linux/blk.h" +#define NEW_MULTICAST + +#define FREE_IRQ(i,d) free_irq(i, d) +#define REQUEST_IRQ(i,h,f,n,d) request_irq(i,h,f,n,d) +#define IRQ(a,b,c) (a,b,c) +#define DEV_ID dev_id + +#if (LINUX_VERSION_CODE < VERSION(2,0,16)) +#define init_waitqueue(p) (*(p) = NULL) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,4)) && !defined(__alpha__) +#define FS_SIZE_T int +#define U_FS_SIZE_T int +#else +#if (LINUX_VERSION_CODE < VERSION(2,1,60)) +#define FS_SIZE_T long +#define U_FS_SIZE_T unsigned long +#else +#define FS_SIZE_T ssize_t +#define U_FS_SIZE_T size_t +#endif +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,25)) +#define net_device_stats enet_statistics +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,31)) +#define FS_RELEASE_T void +#else +#define FS_RELEASE_T int +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,38)) +#define test_and_set_bit set_bit +#endif + +#if (LINUX_VERSION_CODE > VERSION(2,1,16)) +#define AUTOCONF_INCLUDED +#define EXPORT_SYMTAB +#endif +#ifdef CONFIG_MODVERSIONS +#define MODVERSIONS 1 +#include <linux/modversions.h> +#endif +#include <linux/module.h> + +#if (LINUX_VERSION_CODE < VERSION(2,1,18)) +#define MODULE_PARM(a,b) extern int __bogus_decl +#undef GET_USE_COUNT +#define GET_USE_COUNT(m) mod_use_count_ +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,0)) +#define copy_from_user memcpy_fromfs +#define copy_to_user memcpy_tofs + +#if (!defined(__alpha__) || (LINUX_VERSION_CODE < VERSION(2,0,34))) +#define ioremap(a,b) \ + (((a) < 0x100000) ? (void *)((u_long)(a)) : vremap(a,b)) +#define iounmap(v) \ + do { if ((u_long)(v) > 0x100000) vfree(v); } while (0) +#endif +/* This is evil... throw away the built-in get_user in 2.0 */ +#include <asm/segment.h> +#undef get_user + +#ifdef __alpha__ +#define get_user(x, ptr) ((x) = __get_user((ptr), sizeof(*(ptr)))) +#undef get_fs_long +#undef put_fs_long +#define get_fs_long(ptr) __get_user((ptr), sizeof(int)) +#define put_fs_long(x, ptr) __put_user((x), (ptr), sizeof(int)) +#else +#define get_user(x, ptr) \ + ((sizeof(*ptr) == 4) ? (x = get_fs_long(ptr)) : \ + (sizeof(*ptr) == 2) ? (x = get_fs_word(ptr)) : \ + (x = get_fs_byte(ptr))) +#endif + +#else /* 2.1.X */ +#include <asm/uaccess.h> +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,45)) +#define F_INODE(file) ((file)->f_inode) +#else +#define F_INODE(file) ((file)->f_dentry->d_inode) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,51)) +#define INVALIDATE_INODES(r) invalidate_inodes(r) +#else +#define INVALIDATE_INODES(r) \ + do { struct super_block *sb = get_super(r); \ + if (sb) invalidate_inodes(sb); } while (0) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,60)) +#define IRQ_MAP(irq, dev) irq2dev_map[irq] = dev +#define FOPS(i,f,b,c,p) (i,f,b,c) +#define FPOS (file->f_pos) +#else +#define IRQ_MAP(irq, dev) while (0) +#define FOPS(i,f,b,c,p) (f,b,c,p) +#define FPOS (*ppos) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,68)) +#define signal_pending(cur) ((cur)->signal & ~(cur)->blocked) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,86)) +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE) +#else +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,89)) +#define POLL_WAIT(f, q, w) poll_wait(q, w) +#else +#define POLL_WAIT(f, q, w) poll_wait(f, q, w) +#endif + +#include <asm/byteorder.h> +#ifndef le16_to_cpu +#define le16_to_cpu(x) (x) +#define le32_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,90)) +#define spin_lock(l) do { } while (0) +#define spin_unlock(l) do { } while (0) +#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0) +#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0) +#else +#include <asm/spinlock.h> +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,104)) +#define mdelay(x) { int i; for (i=0;i<x;i++) udelay(1000); } +#endif + +#define wacquire(w) do { } while (0) +#define wrelease(w) do { } while (0) +#define wsleep(w) interruptible_sleep_on(w) +#define wakeup(w) wake_up_interruptible(w) +#define wsleeptimeout(w,t) interruptible_sleep_on_timeout(w,t) +#if (LINUX_VERSION_CODE < VERSION(2,1,127)) +#define interruptible_sleep_on_timeout(w,t) \ + ({(current->timeout=jiffies+(t));wsleep(w);current->timeout;}) +#define schedule_timeout(t) \ + do { current->timeout = jiffies+(t); schedule(); } while (0) +#endif + +#include <asm/io.h> +#ifndef readw_ns +#ifdef __powerpc__ +#define readw_ns(p) ld_be16((volatile unsigned short *)(p)) +#define readl_ns(p) ld_be32((volatile unsigned *)(p)) +#define writew_ns(v,p) st_le16((volatile unsigned short *)(p),(v)) +#define writel_ns(v,p) st_le32((volatile unsigned *)(p),(v)) +#define inw_ns(p) in_be16((unsigned short *)((p)+_IO_BASE)) +#define inl_ns(p) in_be32((unsigned *)((p)+_IO_BASE)) +#define outw_ns(v,p) out_be16((unsigned short *)((p)+_IO_BASE),(v)) +#define outl_ns(v,p) out_be32((unsigned *)((p)+_IO_BASE),(v)) +#else +#define readw_ns(p) readw(p) +#define readl_ns(p) readl(p) +#define writew_ns(v,p) writew(v,p) +#define writel_ns(v,p) writel(v,p) +#define inw_ns(p) inw(p) +#define inl_ns(p) inl(p) +#define outw_ns(v,p) outw(v,p) +#define outl_ns(v,p) outl(v,p) +#endif +#endif +#ifndef insw_ns +#define insw_ns(p,b,l) insw(p,b,l) +#define insl_ns(p,b,l) insl(p,b,l) +#define outsw_ns(p,b,l) outsw(p,b,l) +#define outsl_ns(p,b,l) outsl(p,b,l) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,93)) +#include <linux/bios32.h> +#endif +#include <linux/pci.h> +#ifndef PCI_FUNC +#define PCI_FUNC(devfn) ((devfn)&7) +#define PCI_SLOT(devfn) ((devfn)>>3) +#define PCI_DEVFN(dev,fn) (((dev)<<3)|((fn)&7)) +#endif + +#if (LINUX_VERSION_CODE > VERSION(2,1,117)) +#define NULL_FLUSH NULL, +#else +#define NULL_FLUSH +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,126)) +#define SCSI_DISK0_MAJOR SCSI_DISK_MAJOR +#endif + +typedef unsigned long k_time_t; +#define ACQUIRE_RESOURCE_LOCK do {} while (0) +#define RELEASE_RESOURCE_LOCK do {} while (0) + +#endif /* _LINUX_K_COMPAT_H */ diff --git a/klaptopdaemon/linux/mem_op.h b/klaptopdaemon/linux/mem_op.h new file mode 100644 index 0000000..85f1ba2 --- /dev/null +++ b/klaptopdaemon/linux/mem_op.h @@ -0,0 +1,120 @@ +/* + * mem_op.h 1.8 1998/07/17 10:12:23 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_MEM_OP_H +#define _LINUX_MEM_OP_H + +/* + If UNSAFE_MEMCPY is defined, we use the (optimized) system routines + to copy between a card and kernel memory. These routines do 32-bit + operations which may not work with all PCMCIA controllers. The + safe versions defined here will do only 8-bit and 16-bit accesses. +*/ + +#ifdef UNSAFE_MEMCPY + +#define copy_from_pc memcpy_fromio +#define copy_to_pc memcpy_toio + +static inline void copy_pc_to_user(void *to, const void *from, size_t n) +{ + size_t odd = (n & 3); + n -= odd; + while (n) { + put_user(readl_ns(from), (int *)to); + (char *)from += 4; (char *)to += 4; n -= 4; + } + while (odd--) + put_user(readb((char *)from++), (char *)to++); +} + +static inline void copy_user_to_pc(void *to, const void *from, size_t n) +{ + int l; + char c; + size_t odd = (n & 3); + n -= odd; + while (n) { + get_user(l, (int *)from); + writel_ns(l, to); + (char *)to += 4; (char *)from += 4; n -= 4; + } + while (odd--) { + get_user(c, (char *)from++); + writeb(c, (char *)to++); + } +} + +#else /* UNSAFE_MEMCPY */ + +static inline void copy_from_pc(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + *(u_short *)to = readw_ns(from); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + *(u_char *)to = readb(from); +} + +static inline void copy_to_pc(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + writew_ns(*(u_short *)from, to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + writeb(*(u_char *)from, to); +} + +static inline void copy_pc_to_user(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + put_user(readw_ns(from), (short *)to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + put_user(readb(from), (char *)to); +} + +static inline void copy_user_to_pc(void *to, const void *from, size_t n) +{ + short s; + char c; + size_t odd = (n & 1); + n -= odd; + while (n) { + get_user(s, (short *)from); + writew_ns(s, to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) { + get_user(c, (char *)from); + writeb(c, to); + } +} + +#endif /* UNSAFE_MEMCPY */ + +#endif /* _LINUX_MEM_OP_H */ diff --git a/klaptopdaemon/linux/memory.h b/klaptopdaemon/linux/memory.h new file mode 100644 index 0000000..d7aa9de --- /dev/null +++ b/klaptopdaemon/linux/memory.h @@ -0,0 +1,30 @@ +/* + * memory.h 1.3 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_MEMORY_H +#define _LINUX_MEMORY_H + +typedef struct erase_info_t { + u_long Offset; + u_long Size; +} erase_info_t; + +#define MEMGETINFO _IOR('M', 1, region_info_t) +#define MEMERASE _IOW('M', 2, erase_info_t) + +#endif /* _LINUX_MEMORY_H */ diff --git a/klaptopdaemon/linux/ss.h b/klaptopdaemon/linux/ss.h new file mode 100644 index 0000000..57ad769 --- /dev/null +++ b/klaptopdaemon/linux/ss.h @@ -0,0 +1,113 @@ +/* + * ss.h 1.18 1998/10/01 20:54:49 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * <[email protected]>. Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_SS_H +#define _LINUX_SS_H + +/* For RegisterCallback */ +typedef struct ss_callback_t { + void (*handler)(void *info, u_int events); + void *info; +} ss_callback_t; + +/* Definitions for card status flags for GetStatus */ +#define SS_WRPROT 0x0001 +#define SS_CARDLOCK 0x0002 +#define SS_EJECTION 0x0004 +#define SS_INSERTION 0x0008 +#define SS_BATDEAD 0x0010 +#define SS_BATWARN 0x0020 +#define SS_READY 0x0040 +#define SS_DETECT 0x0080 +#define SS_POWERON 0x0100 +#define SS_GPI 0x0200 +#define SS_STSCHG 0x0400 +#define SS_CARDBUS 0x0800 +#define SS_3VCARD 0x1000 +#define SS_XVCARD 0x2000 + +/* for InquireSocket */ +typedef struct socket_cap_t { + u_int features; + u_int irq_mask; + u_int map_size; + u_char pci_irq; + u_char cardbus; +} socket_cap_t; + +/* InquireSocket features */ +#define SS_HAS_PAGE_REGS 0x0001 + +/* for GetSocket, SetSocket */ +typedef struct socket_state_t { + u_int flags; + u_int csc_mask; + u_char Vcc, Vpp; + u_char io_irq; +} socket_state_t; + +/* Various card configuration flags */ +#define SS_PWR_AUTO 0x0010 +#define SS_IOCARD 0x0020 +#define SS_RESET 0x0040 +#define SS_DMA_MODE 0x0080 +#define SS_SPKR_ENA 0x0100 +#define SS_OUTPUT_ENA 0x0200 + +/* Flags for I/O port and memory windows */ +#define MAP_ACTIVE 0x01 +#define MAP_16BIT 0x02 +#define MAP_AUTOSZ 0x04 +#define MAP_0WS 0x08 +#define MAP_WRPROT 0x10 +#define MAP_ATTRIB 0x20 +#define MAP_USE_WAIT 0x40 +#define MAP_PREFETCH 0x80 + +/* Use this just for bridge windows */ +#define MAP_IOSPACE 0x20 + +typedef struct pccard_io_map { + u_char map; + u_char flags; + u_short speed; + u_short start, stop; +} pccard_io_map; + +typedef struct pccard_mem_map { + u_char map; + u_char flags; + u_short speed; + u_long sys_start, sys_stop; + u_int card_start; +} pccard_mem_map; + +typedef struct cb_bridge_map { + u_char map; + u_char flags; + u_int start, stop; +} cb_bridge_map; + +enum ss_service { + SS_RegisterCallback, SS_InquireSocket, + SS_GetStatus, SS_GetSocket, SS_SetSocket, + SS_GetIOMap, SS_SetIOMap, SS_GetMemMap, SS_SetMemMap, + SS_GetBridge, SS_SetBridge, SS_ProcSetup +}; + +#endif /* _LINUX_SS_H */ diff --git a/klaptopdaemon/linux/version.h b/klaptopdaemon/linux/version.h new file mode 100644 index 0000000..86f556e --- /dev/null +++ b/klaptopdaemon/linux/version.h @@ -0,0 +1,4 @@ +/* version.h 1.55 1998/02/25 22:21:07 (David Hinds) */ + +#define CS_RELEASE "3.0.9" +#define CS_RELEASE_CODE 0x3009 diff --git a/klaptopdaemon/main.cpp b/klaptopdaemon/main.cpp new file mode 100644 index 0000000..9dc0419 --- /dev/null +++ b/klaptopdaemon/main.cpp @@ -0,0 +1,305 @@ +/* + * main.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include <klocale.h> +#include <kprocess.h> +#include <kconfig.h> +#include <kglobal.h> +#include <qlayout.h> +#include <unistd.h> +#include <fcntl.h> + +#include "main.h" +#include "version.h" +#include "warning.h" +#include "power.h" +#include "battery.h" +#include "buttons.h" +#include "pcmcia.h" +#include "acpi.h" +#include "apm.h" +#include "sony.h" +#include "profile.h" +#include "portable.h" +extern void wake_laptop_daemon(); + + +extern "C" +{ + + KDE_EXPORT KCModule *create_pcmcia(QWidget *parent, const char *) + { + return new PcmciaConfig(parent, "kcmlaptop"); + } + + KDE_EXPORT KCModule *create_bwarning(QWidget *parent, const char *) + { + return new WarningConfig(0, parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_cwarning(QWidget *parent, const char *) + { + return new WarningConfig(1, parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_battery(QWidget *parent, const char *) + { + return new BatteryConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_power(QWidget *parent, const char *) + { + return new PowerConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_acpi(QWidget *parent, const char *) + { + return new AcpiConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_apm(QWidget *parent, const char *) + { + return new ApmConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_Profile(QWidget *parent, const char *) + { + return new ProfileConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_sony(QWidget *parent, const char *) + { + return new SonyConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_buttons(QWidget *parent, const char *) + { + return new ButtonsConfig(parent, "kcmlaptop"); + } + + KDE_EXPORT void init_battery() + { + KConfig config("kcmlaptoprc", true /*readonly*/, false /*no globals*/); + config.setGroup("BatteryDefault"); + bool enable = false; + if (!config.hasKey("Enable")) { // if they have APM or PCMCIA, Enable=true + struct power_result pr = laptop_portable::poll_battery_state(); + if ((laptop_portable::has_power_management() && + !(pr.powered && + (pr.percentage < 0 || pr.percentage == 0xff)))|| + 0 == access("/var/run/stab", R_OK|F_OK) || + 0 == access("/var/lib/pcmcia/stab", R_OK|F_OK)) + enable = true; + } else { + enable = config.readBoolEntry("Enable", false); + } + if (!enable) + return; + wake_laptop_daemon(); + } + + KDE_EXPORT KCModule *create_laptop(QWidget *parent, const char *) + { + return new LaptopModule(parent, "kcmlaptop"); + } + + KDE_EXPORT void init_laptop() + { + init_battery(); + } +} + + + +LaptopModule::LaptopModule(QWidget *parent, const char *) + : KCModule(parent, "kcmlaptop") +{ + { // export ACPI options + KConfig config("kcmlaptoprc", true /*readonly*/, false /*no globals*/); + config.setGroup("AcpiDefault"); + + bool enablestandby = config.readBoolEntry("EnableStandby", false); + bool enablesuspend = config.readBoolEntry("EnableSuspend", false); + bool enablehibernate = config.readBoolEntry("EnableHibernate", false); + bool enableperformance = config.readBoolEntry("EnablePerformance", false); + bool enablethrottle = config.readBoolEntry("EnableThrottle", false); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config.setGroup("ApmDefault"); + + enablestandby = config.readBoolEntry("EnableStandby", false); + enablesuspend = config.readBoolEntry("EnableSuspend", false); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + config.setGroup("SoftwareSuspendDefault"); + enablehibernate = config.readBoolEntry("EnableHibernate", false); + laptop_portable::software_suspend_set_mask(enablehibernate); + } + QVBoxLayout *layout = new QVBoxLayout(this); + tab = new QTabWidget(this); + layout->addWidget(tab); + + battery = new BatteryConfig(parent, "kcmlaptop"); + tab->addTab(battery, i18n("&Battery")); + connect(battery, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + power = new PowerConfig(parent, "kcmlaptop"); + tab->addTab(power, i18n("&Power Control")); + connect(power, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + warning = new WarningConfig(0, parent, "kcmlaptop"); + tab->addTab(warning, i18n("Low Battery &Warning")); + connect(warning, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + critical = new WarningConfig(1, parent, "kcmlaptop"); + tab->addTab(critical, i18n("Low Battery &Critical")); + connect(critical, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + QStringList profile_list; + int current_profile; + bool *active_list; + bool has_profile = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttling = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + if (laptop_portable::has_brightness() || has_profile || has_throttling) { + profile = new ProfileConfig(parent, "kcmlaptop"); + tab->addTab(profile, i18n("Default Power Profiles")); + connect(profile, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + profile = 0; + } + if (laptop_portable::has_button(laptop_portable::LidButton) || laptop_portable::has_button(laptop_portable::PowerButton)) { + buttons = new ButtonsConfig(parent, "kcmlaptop"); + tab->addTab(buttons, i18n("Button Actions")); + connect(buttons, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + buttons = 0; + } + if (laptop_portable::has_acpi()) { + acpi = new AcpiConfig(parent, "kcmlaptop"); + tab->addTab(acpi, i18n("&ACPI Config")); + connect(acpi, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + acpi = 0; + } + if (laptop_portable::has_apm()) { + apm = new ApmConfig(parent, "kcmlaptop"); + tab->addTab(apm, i18n("&APM Config")); + connect(apm, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + apm = 0; + } + if (::access("/dev/sonypi", F_OK) == 0) { + bool do_sony = 1; + if (::access("/dev/sonypi", R_OK) == 0) { + int fd = ::open("/dev/sonypi", O_RDONLY); // make sure the driver's there as well as the /dev inode + if (fd >= 0) { + ::close(fd); + } else { + do_sony = 0; + } + } + if (do_sony) { + sony = new SonyConfig(parent, "kcmlaptop"); + tab->addTab(sony, i18n("&Sony Laptop Config")); + connect(sony, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + sony = 0; + } + } else { + sony = 0; + } + + KAboutData* about = + new KAboutData("kcmlaptop", I18N_NOOP("Laptop Battery Configuration"), LAPTOP_VERSION, + I18N_NOOP("Battery Control Panel Module"), + KAboutData::License_GPL, + I18N_NOOP("(c) 1999 Paul Campbell"), 0, 0); + //about->addAuthor("NAME", 0, "e-mail addy"); + setAboutData( about ); +} + +void LaptopModule::load() +{ + battery->load(); + warning->load(); + critical->load(); + power->load(); + if (apm) + apm->load(); + if (acpi) + acpi->load(); + if (profile) + profile->load(); + if (sony) + sony->load(); + if (buttons) + buttons->load(); +} + +void LaptopModule::save() +{ + battery->save(); + warning->save(); + critical->save(); + power->save(); + if (profile) + profile->save(); + if (acpi) + acpi->save(); + if (apm) + apm->save(); + if (sony) + sony->save(); + if (buttons) + buttons->save(); +} + + +void LaptopModule::defaults() +{ + battery->defaults(); + warning->defaults(); + critical->defaults(); + power->defaults(); + if (acpi) + acpi->defaults(); + if (apm) + apm->defaults(); + if (profile) + profile->defaults(); + if (sony) + sony->defaults(); + if (buttons) + buttons->defaults(); +} + +QString LaptopModule::quickHelp() const +{ + return i18n("<h1>Laptop Battery</h1>This module allows you to monitor " + "your batteries. To make use of this module, you must have power management software " + "installed. (And, of course, you should have batteries in your " + "machine.)"); +} + + +void LaptopModule::moduleChanged(bool state) +{ + emit changed(state); +} + + +#include "main.moc" diff --git a/klaptopdaemon/main.h b/klaptopdaemon/main.h new file mode 100644 index 0000000..81d6e41 --- /dev/null +++ b/klaptopdaemon/main.h @@ -0,0 +1,82 @@ +/* + * main.h + * + * Copyright (c) 2002 Paul Campbell [email protected] + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __MAIN_H__ +#define __MAIN_H__ + + +#include <qtabwidget.h> + + +#include <kcmodule.h> + + +class WarningConfig; +class BatteryConfig; +class PowerConfig; +class AcpiConfig; +class ApmConfig; +class SonyConfig; +class ProfileConfig; +class ButtonsConfig; + +class LaptopModule : public KCModule +{ + Q_OBJECT + +public: + + LaptopModule(QWidget *parent, const char *name); + + void load(); + void save(); + void defaults(); + QString quickHelp() const; + + + +protected slots: + + void moduleChanged(bool state); + + +private: + + QTabWidget *tab; + + WarningConfig *warning; + WarningConfig *critical; + BatteryConfig *battery; + PowerConfig *power; + AcpiConfig *acpi; + ApmConfig *apm; + ProfileConfig *profile; + SonyConfig *sony; + ButtonsConfig *buttons; +}; + + +#endif + + diff --git a/klaptopdaemon/makecrc.cpp b/klaptopdaemon/makecrc.cpp new file mode 100644 index 0000000..ce3d415 --- /dev/null +++ b/klaptopdaemon/makecrc.cpp @@ -0,0 +1,38 @@ +/* + * makecrc.cpp + * + * Copyright (c) 2003 Paul Campbell <[email protected]> + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + + + +#include "checkcrc.h" + +int main(int, char**) +{ + unsigned long len, crc; + checkcrc("./klaptop_acpi_helper", len, crc); + printf("#ifndef _CRCRESULT_H_\n"); + printf("#define _CRCRESULT_H_\n"); + printf("static unsigned long file_len = 0x%lx;\n", len); + printf("static unsigned long file_crc = 0x%lx;\n", crc); + printf("#endif\n"); + return(0); +} diff --git a/klaptopdaemon/pcmcia.cpp b/klaptopdaemon/pcmcia.cpp new file mode 100644 index 0000000..ed17789 --- /dev/null +++ b/klaptopdaemon/pcmcia.cpp @@ -0,0 +1,122 @@ +/* + * pcmcia.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include <qfileinfo.h> +#include <qlayout.h> + +#include <kglobal.h> +#include <klocale.h> +#include <stdio.h> + +#include "pcmcia.h" +#include "portable.h" +#include "version.h" + +PcmciaConfig::PcmciaConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KAboutData *about = + new KAboutData(I18N_NOOP("kcmlaptop"), + I18N_NOOP("KDE Panel System Information Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 1999 - 2002 Paul Campbell")); + about->addAuthor("Paul Campbell", 0, "[email protected]"); + setAboutData( about ); + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + label0 = laptop_portable::pcmcia_info(0, this); + label0_text = laptop_portable::pcmcia_info(1, this); + label1 = laptop_portable::pcmcia_info(2, this); + label1_text = laptop_portable::pcmcia_info(3, this); + + + QVBoxLayout *top_layout = new QVBoxLayout(this, 15, 5); + QGridLayout *top_grid = new QGridLayout(2, 2); + top_layout->addLayout(top_grid); + + top_grid->setColStretch(0, 0); + top_grid->setColStretch(1, 1); + top_grid->addRowSpacing(0, 40); + top_grid->addRowSpacing(1, 40); + + label0->setFixedSize(80, 24); + top_grid->addWidget(label0, 0, 0); + label0_text->adjustSize(); + top_grid->addWidget(label0_text, 0, 1); + + label1->setFixedSize(80, 24); + top_grid->addWidget(label1, 1, 0); + label1_text->adjustSize(); + top_grid->addWidget(label1_text, 1, 1); + + + top_layout->addStretch(1); + + QHBoxLayout *v1 = new QHBoxLayout; + top_layout->addLayout(v1, 0); + v1->addStretch(1); + QString s1 = LAPTOP_VERSION; + QString s2 = i18n("Version: ")+s1; + QLabel* vers = new QLabel(s2, this); + vers->setMinimumSize(vers->sizeHint()); + v1->addWidget(vers, 0); + + top_layout->activate(); + + load(); + setButtons(Help); +} + + +void PcmciaConfig::save() +{ +} + +void PcmciaConfig::load() +{ +} + +void PcmciaConfig::defaults() +{ +} + + +void PcmciaConfig::changed() +{ + emit KCModule::changed(true); +} + + +QString PcmciaConfig::quickHelp() const +{ + return i18n("<h1>PCMCIA Config</h1>This module shows information about " + "the PCMCIA cards in your system, if there are PCMCIA cards."); +} + +#include "pcmcia.moc" diff --git a/klaptopdaemon/pcmcia.h b/klaptopdaemon/pcmcia.h new file mode 100644 index 0000000..e163742 --- /dev/null +++ b/klaptopdaemon/pcmcia.h @@ -0,0 +1,70 @@ +/* + * pcmcia.h + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __PCMCIACONFIG_H__ +#define __PCMCIACONFIG_H__ + +#include <qdialog.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qlcdnumber.h> +#include <qradiobutton.h> +#include <qbuttongroup.h> + +#include <kapplication.h> +#include <knuminput.h> + +#include <kcmodule.h> +#include <kaboutdata.h> + +class PcmciaConfig : public KCModule +{ + Q_OBJECT +public: + PcmciaConfig( QWidget *parent=0, const char* name=0); + + void save( void ); + void load(); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void changed(); + + +private: + void GetSettings( void ); + + QLabel *label0; + QLabel *label1; + QLabel *label0_text; + QLabel *label1_text; + + +}; + +#endif + diff --git a/klaptopdaemon/pics/Makefile.am b/klaptopdaemon/pics/Makefile.am new file mode 100644 index 0000000..2828fc2 --- /dev/null +++ b/klaptopdaemon/pics/Makefile.am @@ -0,0 +1,6 @@ +# $Id$ +# kdebase/kcontrol/input/pics +SUBDIRS = actions + +KDE_ICON = laptop_battery laptop laptop_pcmcia klaptopdaemon + diff --git a/klaptopdaemon/pics/README b/klaptopdaemon/pics/README new file mode 100644 index 0000000..29a1b13 --- /dev/null +++ b/klaptopdaemon/pics/README @@ -0,0 +1,36 @@ +Notes about laptop daemon's icons: + + lo16-app-klaptopdaemon.png - is only used for the context menu + only the 16x16 is actually needed + + in fact with recent changes to the iconloader icons other than + the 16x16 (really 20x20) are BAD - please don't create them + + the 3 icons in the action directory: + laptop_charge/laptop_concharge/laptop_nobattery + + are 'special' - they are read by the application and + modified on-the-fly to create a bar-graph of how full + the battery is - you can't just edit them the way you would + a normal icon - basically any white pixels will be replaced + with a proportional number of blue ones from the bottom of + the icon to the top (so pure white pixels are 'magic' and + should be treated as the portion of the icon that is the graph) + you can use slightly off-white or a not-quite-saturated + white if you want 'white' + + I'd love some cool new battery icons but please contact me + if you need some testing before committing + + + + Paul Campbell - laptop support author + +We also have some contributed icons: + +the 2 'alt_' ones came from Percy Leonhardt <percy at eris23.de> +the 3 'alt2_' ones came from Keunwoo Lee <klee at cs.washington.edu> +the 2 'alt3_' ones came from Jason Dixon <jasondixon at myrealbox.com> + +thanks guys! diff --git a/klaptopdaemon/pics/actions/Makefile.am b/klaptopdaemon/pics/actions/Makefile.am new file mode 100644 index 0000000..4f9cf71 --- /dev/null +++ b/klaptopdaemon/pics/actions/Makefile.am @@ -0,0 +1,3 @@ +klaptopdaemoniconsdir = $(kde_datadir)/klaptopdaemon/icons +klaptopdaemonicons_ICON = AUTO + diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png Binary files differnew file mode 100644 index 0000000..3018b38 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png Binary files differnew file mode 100644 index 0000000..6c4951b --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png Binary files differnew file mode 100644 index 0000000..743d809 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png Binary files differnew file mode 100644 index 0000000..fd3e6ff --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png Binary files differnew file mode 100644 index 0000000..87962a6 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png Binary files differnew file mode 100644 index 0000000..8a257fd --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png diff --git a/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png Binary files differnew file mode 100644 index 0000000..211b5f6 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png b/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png Binary files differnew file mode 100644 index 0000000..717d37f --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png b/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png Binary files differnew file mode 100644 index 0000000..7c6b8bc --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png Binary files differnew file mode 100644 index 0000000..e5e8418 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png diff --git a/klaptopdaemon/pics/actions/cr16-action-power.png b/klaptopdaemon/pics/actions/cr16-action-power.png Binary files differnew file mode 100644 index 0000000..ac7deec --- /dev/null +++ b/klaptopdaemon/pics/actions/cr16-action-power.png diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png b/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png Binary files differnew file mode 100644 index 0000000..4a9fad1 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png b/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png Binary files differnew file mode 100644 index 0000000..07e9f0d --- /dev/null +++ b/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png b/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png Binary files differnew file mode 100644 index 0000000..1eda606 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_power.png b/klaptopdaemon/pics/actions/cr22-action-laptop_power.png Binary files differnew file mode 100644 index 0000000..92b6328 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr22-action-laptop_power.png diff --git a/klaptopdaemon/pics/actions/cr32-action-power.png b/klaptopdaemon/pics/actions/cr32-action-power.png Binary files differnew file mode 100644 index 0000000..e785191 --- /dev/null +++ b/klaptopdaemon/pics/actions/cr32-action-power.png diff --git a/klaptopdaemon/pics/cr128-app-laptop_battery.png b/klaptopdaemon/pics/cr128-app-laptop_battery.png Binary files differnew file mode 100644 index 0000000..48561f6 --- /dev/null +++ b/klaptopdaemon/pics/cr128-app-laptop_battery.png diff --git a/klaptopdaemon/pics/cr16-app-laptop_battery.png b/klaptopdaemon/pics/cr16-app-laptop_battery.png Binary files differnew file mode 100644 index 0000000..7deaf05 --- /dev/null +++ b/klaptopdaemon/pics/cr16-app-laptop_battery.png diff --git a/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png Binary files differnew file mode 100644 index 0000000..e8eda78 --- /dev/null +++ b/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png diff --git a/klaptopdaemon/pics/cr32-app-laptop_battery.png b/klaptopdaemon/pics/cr32-app-laptop_battery.png Binary files differnew file mode 100644 index 0000000..5358826 --- /dev/null +++ b/klaptopdaemon/pics/cr32-app-laptop_battery.png diff --git a/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png Binary files differnew file mode 100644 index 0000000..534e548 --- /dev/null +++ b/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png diff --git a/klaptopdaemon/pics/cr48-app-laptop_battery.png b/klaptopdaemon/pics/cr48-app-laptop_battery.png Binary files differnew file mode 100644 index 0000000..4038d44 --- /dev/null +++ b/klaptopdaemon/pics/cr48-app-laptop_battery.png diff --git a/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png Binary files differnew file mode 100644 index 0000000..faad8ff --- /dev/null +++ b/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png diff --git a/klaptopdaemon/pics/cr64-app-laptop_battery.png b/klaptopdaemon/pics/cr64-app-laptop_battery.png Binary files differnew file mode 100644 index 0000000..8a6a92d --- /dev/null +++ b/klaptopdaemon/pics/cr64-app-laptop_battery.png diff --git a/klaptopdaemon/pics/crsc-app-laptop_battery.svgz b/klaptopdaemon/pics/crsc-app-laptop_battery.svgz Binary files differnew file mode 100644 index 0000000..07ae4e5 --- /dev/null +++ b/klaptopdaemon/pics/crsc-app-laptop_battery.svgz diff --git a/klaptopdaemon/portable.cpp b/klaptopdaemon/portable.cpp new file mode 100644 index 0000000..f56dc1e --- /dev/null +++ b/klaptopdaemon/portable.cpp @@ -0,0 +1,3087 @@ +/* + * portable.cpp + * + * $Id$ + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// this file contains the machine specific laptop power management stuff +// to add support for your own OS this is should be the only place you need +// to change - to add your own stuff insert above the line marked +// 'INSERT HERE' : +// +// #ifdef MY_OS" +// .. copy of linux code or whatever you want to use as a base +// # else +// +// then tag an extra '#endif' at the end +// +// There is support for the following OSsen right now: +// +// Linux (#if __linux__) +// FreeBSD (#elif __FreeBSD__) +// NetBSD (#elif __NetBSD_APM__) +// generic nothing (#else) +// +// +// The code here is written in a C rather than C++ like to encourage +// people more used to kernel types to do stuff here +// +// If you have any problems, questions, whatever please get in touch +// +// Paul Campbell +// +// +// Thanks to Cajus Pollmeier <[email protected]> +// and Robert Ellis Parrott <[email protected]> +// who both provided ACPI support +// and Volker Krause <[email protected]> who provided ACPI bug fixes +// + +#include <config.h> +#include <klocale.h> +#include <kdebug.h> +#include <stdio.h> +#include "portable.h" + +#ifdef __linux__ + +/* +** This is the Linux-specific laptop code. +*/ +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <time.h> +#include <stdlib.h> +#include <math.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <dirent.h> +#include <qpushbutton.h> +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qstringlist.h> +#include <qstring.h> +#include <qobject.h> +#include <qregexp.h> +#include <qiodevice.h> +#include <qlayout.h> +#include <qvgroupbox.h> +#include <qvaluevector.h> + +#include <kactivelabel.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kprocess.h> +#include <krichtextlabel.h> + +// ibm specific stuff +extern "C"{ +#include "thinkpad_common.h" +#include "smapi.h" +#include "smapidev.h" +} + +// +// here's the Linux specific laptop control panel stuff +// + +typedef struct apm_info { + unsigned int apm_flags; + unsigned int ac_line_status; + int battery_percentage; + int battery_time; +} apm_info; + +static int +apm_read(apm_info *ap) +{ + FILE *f = 0; + char tmp2[10]; + int tmp, s; + unsigned int utmp; + char version[256]; + + f = fopen("/proc/apm", "r"); + if (f == NULL) + return(1); + s = fscanf(f, "%255s %d.%d %x %x %x %x %d%% %d %s\n", + version, + &tmp, + &tmp, + &ap->apm_flags, + &ap->ac_line_status, + &utmp, + &utmp, + &ap->battery_percentage, + &ap->battery_time, + tmp2); + fclose(f); + if (s < 9) + return(1); + if (version[0] == 'B') + return(2); + if (ap->battery_percentage > 100) + ap->battery_percentage = -1; + if (strcmp(tmp2, "sec") == 0) + ap->battery_time /= 60; + return(0); +} + + +// 0 => unknown +// 1 => have it +// -1 => don't have it +static int pmustate = 0; + +static bool +have_pmu(void) +{ + if (pmustate != 0) + return (pmustate == 1); + if (!access("/proc/pmu", R_OK|X_OK)) { + kdDebug() << "Found powermac PMU. Using that." << endl; + pmustate = 1; + return true; + } + pmustate = -1; + return false; +} + +/* Only supports 1 battery right now - all batteries are merged into one stat */ +static int +pmu_read(apm_info *ap) +{ + int bcnt = 0; + memset(ap, 0, sizeof(apm_info)); + QFile f("/proc/pmu/info"); + if (!f.open(IO_ReadOnly)) + return 1; + + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':', l, false); + if (ll[0].stripWhiteSpace() == "AC Power") { + ap->ac_line_status = ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "line status " << ap->ac_line_status << endl; + } else if (ll[0].stripWhiteSpace() == "Battery count") { + bcnt = ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "batteries: " << bcnt << endl; + } + } + + f.close(); + + int charge = 0; + int timerem = 0; + int maxcharge = 0; + for (int i = 0; i < bcnt; i++) { + QFile bf(QString("/proc/pmu/battery_%1").arg(i)); + if (!bf.open(IO_ReadOnly)) + continue; + + while(!bf.atEnd()) { + QString l; + bf.readLine(l, 500); + QStringList ll = QStringList::split(':', l, false); + if (ll[0].stripWhiteSpace() == "charge") { + charge += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "charge: " << charge << endl; + } else if (ll[0].stripWhiteSpace() == "max_charge") { + maxcharge += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "max charge: " << maxcharge << endl; + } else if (ll[0].stripWhiteSpace() == "time rem.") { + timerem += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "time: " << timerem << endl; + } + } + bf.close(); + } + ap->battery_percentage = int(rint(100.0*float(float(charge)/float(maxcharge)))); + ap->battery_time = timerem; + + if (ap->ac_line_status > 0 || timerem == 0 || + (ap->ac_line_status == 0 && charge > 100 && timerem == 0)) + ap->battery_time = -1; + + return 0; +} + + +struct acpi_battery_info { + int percentage; + bool present; + int cap; + int cap_low; + int remaining; + int rate; + QString name; + QString state_file; + QString info_file; +}; + +static QValueVector<acpi_battery_info> acpi_batteries; +static int acpi_last_known=0; +static int last_seed=1; // increment this to force revaluation + +static unsigned char acpi_ac_ok; + +// +// linux APCI doesn't return useful stuff like how much TIME is left yet +// the 'rate' is not smoothed over time so it's faked out here +// it's not pretty and it's a quick estimate +// +// for the moment we prefer APM +// + +static int +acpi_ac_status() +{ + DIR *dfd; + struct dirent *dp; + FILE *f = NULL; + static char buff[NAME_MAX+50]; + static bool inited=0; + static bool bad=0; + + if (inited) { + if (bad) + return(-1); + f = fopen(buff, "r"); + goto readit; + } + inited = 1; + + dfd = opendir("/proc/acpi/ac_adapter/"); + if (dfd) { + for (;;) { + dp = readdir(dfd); + if (dp == 0) + break; + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + strcpy(buff, "/proc/acpi/ac_adapter/"); + strcat(buff, dp->d_name); + strcat(buff, "/status"); + f = fopen(buff, "r"); + if (!f) { + strcpy(buff, "/proc/acpi/ac_adapter/"); + strcat(buff, dp->d_name); + strcat(buff, "/state"); + f = fopen(buff, "r"); + } + if (f) + break; + } + closedir(dfd); +readit: + if (f) { + for (;;) { + char buff2[1024]; + if (fgets(buff2, sizeof(buff), f) == NULL) + break; + if (strstr(buff2, "Status:") != NULL || + strstr(buff2, "state:") != NULL) { + if (strstr(buff2, "on-line") != NULL) { + fclose(f); + return(1); + } + } + } + fclose(f); + return(0); + } + } + bad=1; + return(-1); +} + +static void acpi_read_batteries() { + QString buff; + QFile *f; + static int test_count = 0; + bool skip = false; + + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + bool present = false; + if ((test_count==0 || acpi_last_known != last_seed) && !bat.info_file.isNull()) { + f = new QFile(bat.info_file); + if (f && f->open(IO_ReadOnly)) { + while(f->readLine(buff,1024) > 0) { + if (buff.contains("design capacity low:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.cap_low = rx.cap(1).toInt(); + if (bat.cap_low < 0) + bat.cap_low = 0; + continue; + } + if (buff.contains("last full capacity:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.cap = rx.cap(1).toInt(); + continue; + } + } + f->close(); + bat.cap -= bat.cap_low; + } + delete f; + } + if (bat.cap <= 0) { + KConfig* config = new KConfig("kcmlaptoprc", true /*readonly*/, false /*useKDEGlobals*/); + config->setGroup("AcpiBattery"); + bat.cap = config->readNumEntry(bat.name,0); + delete config; + } + if (!bat.state_file.isNull()) { + f = new QFile(bat.state_file); + if (f && f->open(IO_ReadOnly)) { + while(f->readLine(buff,1024) > 0) { + if (buff.contains("present rate:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.rate = rx.cap(1).toInt(); + if (bat.rate < 0) + bat.rate = 0; + present = true; + continue; + } + if (buff.contains("remaining capacity:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.remaining = rx.cap(1).toInt(); + bat.remaining -= bat.cap_low; + if (bat.remaining < 0) + bat.remaining = 0; + present = true; + continue; + } + } + f->close(); + } + delete f; + } + if(present && !bat.present) // recheck capacity if a battery was put in + skip = true; + bat.present = present; + if (bat.present) { + if (bat.remaining > bat.cap) { // happens e.g. if the system doesn't provide a capacity value + bat.cap = bat.remaining; + KConfig* config = new KConfig("kcmlaptoprc", false /*readonly*/, false /*useKDEGlobals*/); + config->setGroup("AcpiBattery"); + config->writeEntry(bat.name, bat.cap); + config->sync(); + delete config; + skip = true; + } + if (bat.cap == 0) + bat.percentage = 0; + else + bat.percentage = bat.remaining*100/bat.cap; + } + else + bat.percentage = 0; + } + + if (!skip) { + acpi_last_known = last_seed; + test_count++; + } + else + test_count = 0; + if (test_count > 1000) // every 1000 or so times recheck the battery capacity + test_count = 0; + +} + +static int +acpi_read(apm_info *ap) +{ + int rate, part, total; + int ret = 1; + bool present = 0; + + part = 0; + total = 0; + rate = 0; + + acpi_read_batteries(); + + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + present |= bat.present; + if(bat.present) { + total += bat.cap; + part += bat.remaining; + rate += bat.rate; + } + ret = 0; + } + + // some broken ACPI implementations don't return a rate + // compute a 'fake' rate by diffing remaining values + if (rate == 0) + { + static int last_remaining = 0; + static time_t last_time = 0; + if (last_remaining != 0 + && last_time != 0) + { + int diff_time = time(0) - last_time; + if (diff_time > 0) + rate = (last_remaining - part) * 3600 / diff_time; + } + last_remaining = part; + last_time = time(0); + if (rate < 0) + rate = 0; + } + + static int nrates = 0; + static int saved_rate[8]; + static unsigned char ignore_next = 2; // ignore the first couple + + ap->ac_line_status = 0; + // + // ACPI (unlike nice systems like some APM implementations) doesn't + // tell us how much battery TIME we have left - here we + // do a weighted average of the discharge rate (in mW) and + // figure out how long we have left by dividing it into the + // remaining capacity + // + // because some ACPI implementations return bogus + // rates when charging we can't estimate the battery life + // so we only collect discharge rate data when we're actually + // discharging + // + if (acpi_ac_status() == 1) { + ap->ac_line_status |= 1; + ignore_next = 2; + } else { + // after switching from power to unpowered we often get + // a bad reading from ACPI resulting in bizarre + // readings + if (ignore_next == 0) { + if (nrates < 8) // smooth the power flow + nrates++; // simple box filter + for (int i = 8-1; i > 0; i--) + saved_rate[i] = saved_rate[i-1]; + saved_rate[0] = rate; + } else { + ignore_next--; + } + } + // + // if we haven't got any discharge rate data yet don't return a + // battery time - probably happens when you start up with the + // ac adaptor plugged in + // + if (nrates == 0) { + ap->battery_time = -1; + } else { + rate = 0; + for (int i = 0; i < nrates; i++) + rate += saved_rate[i]; + rate = (rate+2*saved_rate[0])/(nrates+2); // weight it slighly + ap->battery_time = (rate==0 ? -1 : 60*part/rate); + } + ap->battery_percentage = (total==0?0:100*part/total); + if (!present) { + ap->battery_percentage = -1; + ap->battery_time = -1; + } + ap->apm_flags = 0; + return(ret); +} + +static int apm_no_time; +static apm_info apmx = {0,0,0,0}; +static int +has_apm() +{ + static int init = 0; + static int val; + if (init) + return(val); + init = 1; + val = 1; + apm_no_time=0; + if (apm_read(&apmx) || (apmx.apm_flags&0x20)) { + val = 0; + apm_no_time = 1; + } else { + apm_no_time = apmx.battery_time < 0; + } + + if (val == 0) { + val = have_pmu(); + if (val && pmu_read(&apmx)) { + val = 0; + } + } + return(val); +} + +// Power to the powermacs!! +static int +has_pmu() +{ + static int init = 0; + static int val; + if (init) + return val; + init = 1; + val = 1; + if (!QDir("/proc/pmu").exists()) { + val = 0; + } + return val; +} + +static bool software_suspend_is_preferred = false; // user prefers to use SS for hibernate +static bool acpi_helper_ok(bool type); +static bool +has_software_suspend(int type) +{ + static int known=0; + static bool present=0; // functionality seems to be here + static bool available=0; // helper can work + if (known != last_seed) { + known = last_seed; + available = 0; + present = (((::access("/proc/sys/kernel/swsusp", F_OK) == 0) || + (::access("/proc/software_suspend", F_OK) == 0) || + (::access("/proc/suspend2", F_OK) == 0)) && + ::access("/usr/sbin/hibernate", F_OK) == 0); + if (present) { + if (::getuid() == 0) { // running as root + available = ::access("/usr/sbin/hibernate", X_OK) == 0 && acpi_helper_ok(1); + } else { + available = acpi_helper_ok(0); + } + } + } + switch (type) { + case 0: return(present); + case 1: return(present&available&software_suspend_is_preferred); + case 2: return(present&available); + default:return(0); + } +} + +bool +laptop_portable::has_software_suspend(int type) +{ + return(::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool hibernate) +{ + software_suspend_is_preferred = hibernate; +} + + +static int x_acpi_init = 0; +static bool +has_acpi() +{ + static bool val; + static bool checked = 0; + + if (!checked) { + val = ::access("/proc/acpi", F_OK) == 0; + checked = 1; + } + return(val); +} + +static int +has_acpi_power() +{ + static int val; + + if (x_acpi_init) + return(val); + x_acpi_init = 1; + val = 0; + + acpi_batteries.clear(); + + if (acpi_ac_status() >= 0) + acpi_ac_ok = 1; + + QDir battdir("/proc/acpi/battery"); + battdir.setFilter(QDir::Dirs); + if(!battdir.isReadable()) + return(val = 0); + for(uint i = 0; !battdir[i].isNull(); ++i) { + if(battdir[i] == "." || battdir[i] == "..") + continue; + bool ok = 0; + acpi_battery_info bat = {0,0,0,0,0,0,0,0,0}; + QString base = battdir.path() + "/" + battdir[i] + "/"; + QString name(base + "state"); + QFileInfo f(name); + if(f.isReadable()) { + bat.state_file = name; + ok = true; + } else { + name = base + "status"; + f.setFile(name); + if(f.isReadable()) { + bat.state_file = name; + ok = true; + } + } + name = base + "info"; + f.setFile(name); + if(f.isReadable()) { + bat.info_file = name; + ok = true; + } + if (ok) { + bat.name = battdir[i]; + acpi_batteries.append(bat); + val = 1; + } + } + if (!acpi_ac_ok) + val = 0; + return(val); +} + +static unsigned long acpi_sleep_enabled = 0x00; // acpi sleep functions enabled mask + + +static bool +has_acpi_sleep(int state) +{ + static int known=0; + static unsigned long mask=0; + if (known != last_seed) { + known = last_seed; + mask = 0; + + QFile p("/sys/power/state"); + QFile f("/proc/acpi/sleep"); + + if (p.open(IO_ReadOnly)) { + QString l; + QTextStream t(&p); + l = t.readLine(); + QStringList ll = QStringList::split(' ',l,false); + for (QValueListIterator<QString> i = ll.begin(); i!=ll.end(); i++) { + QString s = *i; + + if (s.compare("standby")==0) + mask |= (1<<1); + else if (s.compare("mem")==0) + mask |= (1<<3); + else if (s.compare("disk")==0) + mask |= (1<<4); + } + p.close(); + } + else if (f.open(IO_ReadOnly)) { + QString l; + QTextStream t(&f); + l = t.readLine(); + QStringList ll = QStringList::split(' ',l,false); + for (QValueListIterator<QString> i = ll.begin(); i!=ll.end(); i++) { + QString s = *i; + if (s[0] == 'S') { + int c = s[1].digitValue(); + if (c >= 0 && c <= 9) + mask |= 1<<c; + } + } + f.close(); + } + } + return((mask&acpi_sleep_enabled&(1<<state)) != 0); +} + +static bool acpi_performance_enabled = 0; +static bool acpi_throttle_enabled = 0; +void +laptop_portable::acpi_set_mask(bool standby, bool suspend, bool hibernate, bool perf, bool throttle) +{ + acpi_sleep_enabled = + (standby ? (1<<1)|(1<<2) : 0) | + (suspend ? 1<<3 : 0) | + (hibernate ? 1<<4 : 0); + acpi_performance_enabled = perf; + acpi_throttle_enabled = throttle; + last_seed++; +} + +static void +invoke_acpi_helper(const char *param, const char *param2, const char *param3) +{ + KProcess proc; + proc << KStandardDirs::findExe("klaptop_acpi_helper"); + proc << param; + if (param2) + proc << param2; + if (param3) + proc << param3; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +static unsigned long apm_sleep_enabled = 0x0c; // apm sleep functions enabled mask +static bool +has_apm_sleep(int state) +{ + return((apm_sleep_enabled&(1<<state)) != 0); +} + +void +laptop_portable::apm_set_mask(bool standby, bool suspend) +{ + apm_sleep_enabled = + (standby ? 1<<2 : 0) | + (suspend ? 1<<3 : 0); + last_seed++; +} + +static bool apm_sleep_access_ok(); +static bool acpi_sleep_access_ok(); + +static int +apm_has_time() +{ + return(!apm_no_time); +} + +// +// something changed maybe we need to check out environment again +// +void +laptop_portable::power_management_restart() +{ + last_seed++; + x_acpi_init = 0; +} + +int laptop_portable::has_apm(int type) +{ + switch (type) { + case 0: + return(::has_apm()); + case 1: + return(::has_apm() && ::apm_sleep_access_ok()); + default: + return(0); + } +} + +// +// returns 1 if we support acpi +// +int laptop_portable::has_acpi(int type) +{ + switch (type) { + case 0: + return(::has_acpi_power()); + case 1: + return(::has_acpi() && ::acpi_sleep_access_ok()); + case 3: + return(::has_acpi() &&::acpi_sleep_access_ok() && (::has_acpi_sleep(1)||::has_acpi_sleep(2))); + case 4: + return(::has_acpi() &&::acpi_sleep_access_ok() && ::has_acpi_sleep(3)); + case 5: + return(::has_acpi() &&::acpi_sleep_access_ok() && ::has_acpi_sleep(4)); + default: + return(0); + } +} + +// +// The following code was derived from tpctl for IBM thinkpad support +// (Thomas Hood, Bill Mair - tpctl.sourceforge.net) +// +// we check for the existence of /dev/thinkpad/thinkpad or /dev/thinkpad +// +static const char *ibm_device; +static int ibm_fd = -1; + +static bool has_ibm() +{ + static int known=0; + static bool result; + if (known == last_seed) + return(result); + known = last_seed; + result = 0; + if (ibm_fd >= 0) { + result = 1; + return(1); + } + ibm_device = "/dev/thinkpad/thinkpad"; + if ((ibm_fd = open(ibm_device, O_RDWR)) < 0) { + ibm_device = "/dev/thinkpad"; + if ((ibm_fd = open(ibm_device, O_RDWR)) < 0) + return(0); + } + result = 1; + return(1); +} +// +// returns 1 if we support power management +// +int laptop_portable::has_power_management() +{ + if (::has_apm()) + return 1; + if (::has_pmu()) + return 1; + if (::has_acpi_power()) + return 1; + if (::has_ibm()) + return 1; + // INSERT HERE + return 0; +} +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + if (::has_acpi_power()) + return 1; + if (::apm_has_time()) + return 1; + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + if (::has_acpi()) + return ::acpi_sleep_access_ok() && ::has_acpi_sleep(3); + if (::has_pmu()) + return 1; + if (::has_ibm()) + return 1; + if (::has_apm()) + return ::apm_sleep_access_ok() && ::has_apm_sleep(3); + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + if (::has_pmu()) + return 0; + if (::has_acpi()) + return ::acpi_sleep_access_ok() && (::has_acpi_sleep(1)||::has_acpi_sleep(2)); + if (::has_ibm()) + return 1; + if (::has_apm()) + return ::apm_sleep_access_ok() && ::has_apm_sleep(2); + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux APM] +// +int laptop_portable::has_hibernation() +{ + if (::has_pmu()) + return 0; + if (::has_software_suspend(1)) // must be before acpi + return 1; + if (::has_acpi()) + return ::acpi_sleep_access_ok() && ::has_acpi_sleep(4); + if (::has_ibm()) + return 1; + // INSERT HERE + return 0; +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// + +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + if (access("/proc/acpi", F_OK) == 0) { // probably has default kernel ACPI installed + KActiveLabel* explain = new KActiveLabel(i18n("Your computer seems to have a partial ACPI installation. ACPI was probably enabled, but some of the sub-options were not - you need to enable at least 'AC Adaptor' and 'Control Method Battery' and then rebuild your kernel."), parent); + return(explain); + } + + KActiveLabel* explain = new KActiveLabel(i18n("Your computer doesn't have the Linux APM (Advanced Power Management) or ACPI software installed, or doesn't have the APM kernel drivers installed - check out the <a href=\"http://www.linuxdoc.org/HOWTO/Laptop-HOWTO.html\">Linux Laptop-HOWTO</a> document for information on how to install APM."), parent); + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + if (::has_apm()) { + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nIf you make /usr/bin/apm setuid then you will also " + "be able to choose 'suspend' and 'standby' in the above " + "dialog - check out the help button below to find out " + "how to do this").replace("\n", QString::null), parent); + return(note); + } + if (::has_acpi()) { + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nYou may need to enable ACPI suspend/resume in the ACPI panel").replace("\n", QString::null), parent); + return(note); + } + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nYour system does not support suspend/standby").replace("\n", QString::null), parent); + return(note); +} + +static char tmp0[256], tmp1[256]; +static int present=0; +static +void get_pcmcia_info() +{ + FILE *f = fopen("/var/lib/pcmcia/stab", "r"); + if (!f) f = fopen("/var/run/stab", "r"); + if (f) { + int c; + char *cp; + + present = 1; + cp = tmp0; + for (;;) { + c = fgetc(f); + if (c == EOF || c == '\n') + break; + if (c == ':') { + while ((c = fgetc(f)) == ' ') + ; + if (c == EOF) + break; + for (;;) { + *cp++ = c; + c = fgetc(f); + if (c == EOF || c == '\n') + break; + } + break; + } + } + *cp = 0; + + if (c != EOF) { + cp = tmp1; + for (;;) { + c = fgetc(f); + if (c == EOF) + break; + if (c == ':') { + while ((c = fgetc(f)) == ' ') + ; + if (c == EOF) + break; + for (;;) { + *cp++ = c; + c = fgetc(f); + if (c == EOF || c == '\n') + break; + } + break; + } + } + *cp = 0; + } + + fclose(f); + } else { + present = 0; + } +} + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + if (x == 0) + get_pcmcia_info(); + if (!present) { + if (x == 1) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); + } else { + switch (x) { + case 0: return(new QLabel(i18n("Card 0:"), parent)); + case 1: return(new QLabel(tmp0, parent)); + case 2: return(new QLabel(i18n("Card 1:"), parent)); + default:return(new QLabel(tmp1, parent)); + } + } +} + +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + last_seed++; // make it look for battery removal/return + if (::has_acpi()) { + if (::has_acpi_sleep(1)) { // people seem to argue as to which is 'standby' the S1 people are winning + ::invoke_acpi_helper("--standby", 0, 0); + } else { + ::invoke_acpi_helper("--standby2", 0, 0); + } + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 0; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific standbys here + KProcess proc; + proc << "/usr/bin/apm"; + proc << "--standby"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + last_seed++; // make it look for battery removal/return + + if (::has_pmu()) { + KProcess proc; + proc << "/usr/bin/apm"; + proc << "-f"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result + return; + } + + if (::has_acpi()) { + ::invoke_acpi_helper("--suspend", 0, 0); + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 1; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific suspends here + KProcess proc; + proc << "/usr/bin/apm"; + proc << "--suspend"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + last_seed++; // make it look for battery removal/return + if (::has_software_suspend(1)) { // must be before acpi + ::invoke_acpi_helper("--software-suspend", 0, 0); + return; + } + if (::has_acpi()) { + ::invoke_acpi_helper("--hibernate", 0, 0); + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 2; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific hibernates here +} + +void +laptop_portable::extra_config(QWidget *wp, KConfig *, QVBoxLayout *top_layout) +{ + if (laptop_portable::has_apm(1) || laptop_portable::has_acpi(1)) + return; + if (laptop_portable::has_apm(0)) { + QLabel* explain = new KRichTextLabel( i18n("Your system has APM installed but may not be able to use all " + "of its features without further setup - look in the 'APM Config' " + "tab for information about setting up APM for suspend and resume"), wp); + top_layout->addWidget(explain, 0); + } + if (laptop_portable::has_acpi(0)) { + QLabel* explain = new KRichTextLabel( i18n("Your system has ACPI installed but may not be able to use all " + "of its features without further setup - look in the 'ACPI Config' " + "tab for information about setting up ACPI for suspend and resume"), wp); + top_layout->addWidget(explain, 0); + } +} + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + + apm_info x = {0,0,0,-1}; + if (have_pmu()) { + pmu_read(&x); + } else + if ((::has_acpi_power() ? ::acpi_read(&x) : ::apm_read(&x)) || (x.apm_flags&0x20)) { + // INSERT HERE + p.powered = 0; + p.percentage=0; + p.time = -1; + return p; + } + p.powered = x.ac_line_status&1; + p.percentage = x.battery_percentage; + p.time = x.battery_time; + return(p); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + if (::has_acpi_power()) { + names.clear(); + state.clear(); + values.clear(); + acpi_read_batteries(); + num_batteries = acpi_batteries.count(); + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + names.append(bat.name); + values.append(QString("%1").arg(bat.percentage)); + state.append(bat.present ? "yes" : "no"); + } + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + + +// +// returns the current system load average, -1 if none +// +static QFile lav_file; +static bool lav_inited=0; +static bool lav_openok=0; + +static bool has_lav() +{ + if (!lav_inited) { + lav_inited =1; + lav_file.setName("/proc/loadavg"); + lav_openok = lav_file.open( IO_ReadOnly ); + if (lav_openok) + lav_file.close(); + } + return(lav_openok); +} + +bool laptop_portable::has_lav() +{ + return ::has_lav(); +} + +float laptop_portable::get_load_average() +{ + if (!::has_lav()) + return(-1); + lav_file.open( IO_ReadOnly ); + QString l; + lav_file.readLine(l, 500); + lav_file.close(); + QStringList ll = QStringList::split(' ', l, false); + l = ll[0]; + bool ok; + float f = l.toFloat(&ok); + if (!ok) + f = -1; + return(f); +} + + +int laptop_portable::has_cpufreq() { + struct stat sb; + int rc; + rc = stat("/proc/cpufreq", &sb); + if (rc == 0) { + rc = stat("/proc/cpuinfo", &sb); + if (rc == 0) + return 1; + } + // INSERT HERE + return 0; +} + + +QString laptop_portable::cpu_frequency() { + QString rc; + QFile cf("/proc/cpufreq"); + bool haveProfile = false; + + if (cf.open(IO_ReadOnly)) { + while (!cf.atEnd()) { + QString l; + cf.readLine(l, 500); + if (l.left(3) == "CPU") { + QStringList ll = QStringList::split(' ', l, false); + rc = ll.last(); + haveProfile = true; + break; + } + } + + } + if (haveProfile) { + QFile ci("/proc/cpuinfo"); + if (ci.open(IO_ReadOnly)) { + while (!ci.atEnd()) { + QString l; + ci.readLine(l, 500); + QStringList ll = + QStringList::split(':',l,false); + if (ll.count() != 2) + continue; + if (ll.first().stripWhiteSpace() + == "cpu MHz") { + rc = i18n("%1 MHz (%2)").arg(ll.last().stripWhiteSpace()).arg(rc); + break; + } else if (ll.first().stripWhiteSpace() + == "clock") { + rc = QString("%1 (%2)").arg(ll.last().stripWhiteSpace()).arg(rc); + break; + } + } + } + } + + return rc; +} + +static int sonyFd = -1; +static int has_toshiba_brightness = 0; + +static bool +acpi_helper_ok(bool type) +{ + static int known[2]={0,0}; + static bool known_res[2]; + + if (known[type] == last_seed) + return(known_res[type]); + known[type] = last_seed; + known_res[type] = 0; + struct stat sb; + QString str = KStandardDirs::findExe("klaptop_acpi_helper"); + if (str.isNull() || str.isEmpty()) + return(0); + + if (stat(str.latin1(), &sb) < 0) + return(0); + if (!S_ISREG(sb.st_mode)) + return(0); + if (!type && getuid() != 0 && (sb.st_uid != 0 || !(sb.st_mode&S_ISUID))) + return(0); + if (!(sb.st_mode&0x111)) + return(0); + known_res[type] = 1; + return(1); +} + +static bool +acpi_sleep_access_ok() +{ + static int known=0; + static int known_res=1; + + if (known != last_seed) { + known = last_seed; + known_res = (::access("/proc/acpi/sleep", R_OK|W_OK)==0 && ::acpi_helper_ok(1)) || + (::access("/proc/acpi/sleep", R_OK)==0 && ::acpi_helper_ok(0)) || + (::access("/sys/power/state", R_OK|W_OK)==0 && ::acpi_helper_ok(1)) || + (::access("/sys/power/state", R_OK)==0 && ::acpi_helper_ok(0)); + } + return(known_res); +} + +static bool +apm_helper_ok(bool type) +{ + static int known[2]={0,0}; + static bool known_res[2]; + + if (known[type] == last_seed) + return(known_res[type]); + known[type] = last_seed; + known_res[type] = 0; + struct stat sb; + QString str = "/usr/bin/apm"; + if (str.isNull() || str.isEmpty()) + return(0); + if (stat(str.latin1(), &sb) < 0) + return(0); + if (!S_ISREG(sb.st_mode)) + return(0); + if (!type && getuid() != 0 && (sb.st_uid != 0 || !(sb.st_mode&S_ISUID))) + return(0); + if (!(sb.st_mode&0x111)) + return(0); + known_res[type] = 1; + return(1); +} + +static bool +apm_sleep_access_ok() +{ + static int known=0; + static int known_res=1; + + if (known != last_seed) { + known = last_seed; + known_res = (::access("/proc/apm", R_OK|W_OK)==0 && ::apm_helper_ok(1)) || + (::access("/proc/apm", R_OK)==0 && ::apm_helper_ok(0)); + } + return(known_res); +} + +int +laptop_portable::has_brightness() +{ + static int known=0; + static int known_res=1; + + if (known == last_seed) + return(known_res); + known = last_seed; + if (sonyFd == -1 && ::access("/dev/sonypi", R_OK) == 0) + sonyFd = ::open("/dev/sonypi", O_RDONLY|O_NONBLOCK); + if (sonyFd >= 0) + return(1); + if (::has_acpi() && + (((::access("/proc/acpi/TOSHIBA1/lcd", R_OK|W_OK)==0 || ::access("/proc/acpi/toshiba/lcd", R_OK|W_OK)==0) && ::acpi_helper_ok(1)) || + ((::access("/proc/acpi/TOSHIBA1/lcd", R_OK)==0 || ::access("/proc/acpi/toshiba/lcd", R_OK)==0) && ::acpi_helper_ok(0)))) { + has_toshiba_brightness = 1; + return(1); + } + // check for new devices here + // INSERT HERE + known_res = 0; + return 0; +} + +#define SONYPI_IOCSBRT _IOW('v', 0, unsigned char) + +// +// There are two sorts of brightness calls - ones where we expect the user to raise the brightness themselves +// by doing something (for these we don't allow the panel to go completely dark), and those where the +// laptop software is going to remember the brightness and set it back later (like closing the lid +// where we can go all the way black) +// +// NOTE: some panel interfaces (sony) can't actually go all the way blank anyway so we ignore the blank tag +// +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + if (sonyFd >= 0) { + unsigned char v; + if (val < 0) + val = 0; + if (val > 255) + val = 255; + v = val; + (void)::ioctl(sonyFd, SONYPI_IOCSBRT, &v); + return; + } + if (has_toshiba_brightness) { + char tmp[20]; + + if (val < 0) + val = 0; + if (val > 255) + val = 255; + val >>= 5; + if (val == 0 && !blank) + val = 1; + snprintf(tmp, sizeof(tmp), "%d", val&7); + ::invoke_acpi_helper("--toshibalcd", tmp, 0); + return; + } + // INSERT HERE +} + +int +laptop_portable::get_brightness() // return a val 0-255, or -1 if you can't +{ + if (sonyFd >= 0) + return(-1); // sonypi doesn't seem to return this reliably + + // INSERT HERE + return(-1); // means can't extract it +} + +#define MAP_SIZE 20 +static int acpi_performance_map[MAP_SIZE]; // hidden acpi state map +static bool acpi_performance_enable[MAP_SIZE]; +static QStringList performance_list; +static QString acpi_performance_cpu; +static int acpi_throttle_map[MAP_SIZE]; +static bool acpi_throttle_enable[MAP_SIZE]; +static QStringList throttle_list; +static QString acpi_throttle_cpu; + +static bool +get_acpi_list(char p, int *map, const char *dev, QStringList &list, int &index, QString &cpu, bool get_enable, bool *enable_list) +{ + DIR *dfd; + struct dirent *dp; + unsigned int i = 0; + bool result = 0; + + index = 0; + list.clear(); + dfd = opendir("/proc/acpi/processor/"); + if (dfd) { + for (dp = readdir(dfd);dp ;dp = readdir(dfd)) { + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + QString name("/proc/acpi/processor/"); + name += dp->d_name; + name += dev; + if (!(::access(name.latin1(), R_OK|W_OK)==0 && ::acpi_helper_ok(1)) && + !(::access(name.latin1(), R_OK)==0 && ::acpi_helper_ok(0))) + continue; + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd() && i < MAP_SIZE) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':',l,false); + QString tag = ll[0].stripWhiteSpace(); + bool is_this = tag[0] == '*'; + if (is_this) { + if (tag[1] != p) + continue; + tag.remove(0, 2); + } else { + if (tag[0] != p) + continue; + tag.remove(0, 1); + } + bool ok; + int val = tag.toInt(&ok); + if (ok) { + if (!result) + cpu = dp->d_name; + if (is_this) + index = i; + map[i] = val; + list.append(ll[1].stripWhiteSpace()); + result = 1; + enable_list[i] = 1; + i++; + } + } + f.close(); + + // + // get the limit info if asked for + // + if (get_enable) { + name = QString("/proc/acpi/processor/")+dp->d_name+"/limit"; + f.setName(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd() && i < MAP_SIZE) { + QString l; + f.readLine(l, 500); + if (l.contains("active limit", false)) { + QRegExp rx(QString("%1(\\d+)").arg(p)); + if (rx.search(l) >= 0) { + bool ok; + int min = rx.cap(1).toInt(&ok); + if (ok) { + for (int j = 0; j < min; j++) + enable_list[j] = 0; + + } + } + break; + } + } + f.close(); + } + } + break; + } + } + closedir(dfd); + } + return(result); +} + +#define CPUFREQ_NONE 0 +#define CPUFREQ_24 1 +#define CPUFREQ_25 2 +#define CPUFREQ_SYSFS 3 + +static QString cpufreq_cpu = ""; +static QString cpufreq_minmax_frequency[2]; + +// get CPUFreq scaling policies via the sysfs interface +static int get_cpufreq_sysfs_state(QStringList &states, int ¤t, const QString cpu) { + QString cur, buffer; + + // read current scaling policy + QFile f("/sys/devices/system/cpu/" + cpu + "/cpufreq/scaling_governor"); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 256); + cur = buffer.stripWhiteSpace(); + f.close(); + + // read available scaling policies + states.clear(); + f.setName("/sys/devices/system/cpu/" + cpu + "/cpufreq/scaling_available_governors"); + if(!f.open(IO_ReadOnly)) + return CPUFREQ_NONE; + int count = 0; + if(!f.atEnd()) { + f.readLine(buffer, 1024); + QStringList l = QStringList::split(' ', buffer.stripWhiteSpace(), false); + for(unsigned int i = 0; i < l.size(); ++i, ++count) { + states.append(l[i].stripWhiteSpace()); + if(states[i] == cur) + current = count; + } + } + f.close(); + + return CPUFREQ_SYSFS; +} + +// get CPUFreq scaling policies via the 2.5 /proc interface +// sample output of cat /proc/cpufreq: +// minimum CPU frequency - maximum CPU frequency - policy +// CPU 0 700000 kHz ( 70 %) - 1000000 kHz (100 %) - powersave +static int get_cpufreq_25_state(QStringList &states, int ¤t) { + current = -1; + states.clear(); + + QFile f("/proc/cpufreq"); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 1024); + QRegExp rx("CPU.*\\d+.*(\\d+).*-.*(\\d+).*-\\W*(\\w*)"); + if (rx.search(l) >= 0) { + cpufreq_minmax_frequency[0] = rx.cap(1); + cpufreq_minmax_frequency[1] = rx.cap(2); + if(rx.cap(3) == "performance") + current = 0; + else + current = 1; + break; + } + } + } + f.close(); + + if(current < 0) + return CPUFREQ_NONE; + + // we don't know all available scaling governors, so use only a minimal set + states.append("performance"); + states.append("powersave"); + return CPUFREQ_25; +} + +// get CPUFreq scaling policies via the 2.4 /proc interface +// The old interface doesn't support policies yet, we only get the min and max frequency, +// so we use these as performance states. +static int get_cpufreq_24_state(QStringList &states, int ¤t, const QString cpu) { + QString buffer, cur; + states.clear(); + + // current frequency + QFile f("/proc/sys/cpu/" + cpu + "/speed"); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 16); + f.close(); + cur = buffer.stripWhiteSpace(); + + // read maximal and minimal frequency + const char* files[] = { "max", "min" }; + for(int i = 0; i <= 1; ++i) { + f.setName("/proc/sys/cpu/" + cpu + "/speed-" + files[i]); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 16); + f.close(); + cpufreq_minmax_frequency[i] = buffer; + unsigned int val = buffer.toUInt() / 1000; + states.append(i18n("%1 MHz").arg(val)); + if(buffer.stripWhiteSpace() == cur) + current = i; + } + return CPUFREQ_24; +} + +// check for CPUFreq support and get a list of all available scaling policies +// this method doesn't support multiple CPU's (neither does get_acpi_list() above), +// but this shouldn't be a problem on notebooks... +static int get_cpufreq_state(bool force, QStringList &states, int ¤t) { + static int known = -1; + + // check wether we already know which interface to use + if(!force && known >= 0) { + switch(known) { + case CPUFREQ_SYSFS: + return get_cpufreq_sysfs_state(states, current, cpufreq_cpu); + break; + case CPUFREQ_25: + return get_cpufreq_25_state(states, current); + break; + case CPUFREQ_24: + return get_cpufreq_24_state(states, current, cpufreq_cpu); + break; + default: + return CPUFREQ_NONE; + } + } + + // look for the CPUFreq sysfs interface first + QDir dir("/sys/devices/system/cpu"); + dir.setFilter(QDir::Dirs); + if(dir.isReadable()) { + for(unsigned int i = 0; !dir[i].isNull(); ++i) { + if(dir[i] == "." || dir[i] == "..") + continue; + cpufreq_cpu = dir[i]; + if(get_cpufreq_sysfs_state(states, current, cpufreq_cpu)) + return (known = CPUFREQ_SYSFS); + } + } + + // try the /proc interface from the 2.5 kernel series next + if(get_cpufreq_25_state(states, current)) + return (known = CPUFREQ_25); + + // last chance: the /proc interface from the 2.4 kernel series + dir.setPath("/proc/sys/cpu"); + dir.setFilter(QDir::Dirs); + if(dir.isReadable()) { + for(unsigned int i = 0; !dir[i].isNull(); ++i) { + if(dir[i] == "." || dir[i] == "..") + continue; + cpufreq_cpu = dir[i]; + if(get_cpufreq_24_state(states, current, cpufreq_cpu)) + return (known = CPUFREQ_24); + } + } + + // no CPUFreq support found + return (known = CPUFREQ_NONE); +} + +bool +laptop_portable::get_system_performance(bool force, int ¤t, QStringList &s, bool *&active) // do something to help get system profiles from places like ACPI +{ + if(!acpi_performance_enabled) + return false; + static int known=0; + static int index=0; + static bool result = 0; + if (known != last_seed || force) { + known = last_seed; + performance_list.clear(); + result = 0; + current = 0; + if (::has_acpi()) { + active = acpi_performance_enable; + result = get_acpi_list('P', acpi_performance_map, "/performance", performance_list, index, acpi_performance_cpu, force, acpi_performance_enable); + } + // CPUFreq support + if (!result && get_cpufreq_state(force, performance_list, index)) { + for(unsigned int i = 0; i < performance_list.size(); ++i) + acpi_performance_enable[i] = true; + active = acpi_performance_enable; + result = true; + } + if (!result) { + // INSERT HERE + } + } + current = index; + s = performance_list; + return(result); +} + +bool +laptop_portable::get_system_throttling(bool force, int ¤t, QStringList &s, bool *&active) // do something to help get system throttling data from places like ACPI +{ + static int known=0; + static int index=0; + static bool result = 0; + if (known != last_seed || force) { + known = last_seed; + throttle_list.clear(); + result = 0; + current = 0; + if (::has_acpi() && acpi_throttle_enabled) { + active = acpi_throttle_enable; + result = get_acpi_list('T', acpi_throttle_map, "/throttling", throttle_list, index, acpi_throttle_cpu, force, acpi_throttle_enable); + } + if (!result) { + // INSERT HERE + } + } + current = index; + s = throttle_list; + return(result); +} + +void +laptop_portable::set_system_performance(QString val) // val = string given by get_system_performance above +{ + if(!acpi_performance_enabled) + return; + int current, result; + if((result = get_acpi_list('P', acpi_performance_map, "/performance", performance_list, current, acpi_performance_cpu, false, acpi_performance_enable))) { + char tmp[20]; + int ind = performance_list.findIndex(val); + if (ind < 0 || ind >= MAP_SIZE || current == ind) + return; + snprintf(tmp, sizeof(tmp), "%d", acpi_performance_map[ind]); + tmp[sizeof(tmp)-1]=0; + ::invoke_acpi_helper("--performance", acpi_performance_cpu.latin1(), tmp); + return; + } + // CPUFreq support + if((result = get_cpufreq_state(false, performance_list, current))) { + if(performance_list[current] == val) + return; + QString tmp; + switch(result) { + case CPUFREQ_SYSFS: + invoke_acpi_helper("--cpufreq-sysfs", cpufreq_cpu.latin1(), val.latin1()); + return; + case CPUFREQ_25: + tmp = cpufreq_minmax_frequency[0] + ":" + cpufreq_minmax_frequency[1] + ":" + val; + invoke_acpi_helper("--cpufreq-25", tmp.latin1(), 0); + return; + case CPUFREQ_24: + int target = performance_list.findIndex(val); + invoke_acpi_helper("--cpufreq-24", cpufreq_cpu.latin1(), cpufreq_minmax_frequency[target].latin1()); + return; + } + } + // INSERT HERE + return; +} + +void +laptop_portable::set_system_throttling(QString val) // val = string given by get_system_throttle above +{ + if (::has_acpi()) { + char tmp[20]; + int ind = throttle_list.findIndex(val); + if (ind < 0 || ind >= MAP_SIZE) + return; + snprintf(tmp, sizeof(tmp), "%d", acpi_throttle_map[ind]); + tmp[sizeof(tmp)-1]=0; + ::invoke_acpi_helper("--throttling", acpi_throttle_cpu.latin1(), tmp); + return; + } + // INSERT HERE + return; +} + +static QString acpi_power_name, acpi_lid_name; // names of paths to ACPI lid states + +static bool +acpi_check_button(const char *prefix, QString &result) +{ + DIR *dfd; + struct dirent *dp; + bool v=0; + + dfd = opendir(prefix); + if (dfd) { + for (dp = readdir(dfd);dp ;dp = readdir(dfd)) { + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + QString name(prefix); + name += "/"; + name += dp->d_name; + name += "/state"; + if (::access(name.latin1(), R_OK)!=0) + continue; + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + if (l.contains("state:")) { + result = name; + v = 1; + break; + } + } + f.close(); + if (v) + break; + } + } + closedir(dfd); + } + return(v); +} + +bool +laptop_portable::has_button(LaptopButton l) // true if we have support for a particular button +{ + static int known[2]={0,0}; + static bool result[2] = {0,0}; + int type = (l==LidButton?0:1); + if (known[type] != last_seed) { + result[type] = 0; + known[type] = last_seed; + if (::has_acpi()) { + switch (l) { + case LidButton: + result[type] = ::acpi_check_button("/proc/acpi/button/lid", acpi_lid_name); + break; + case PowerButton: + result[type] = ::acpi_check_button("/proc/acpi/button/power", acpi_power_name); + break; + default: + break; + } + } + if (!result[type] && ::has_ibm() && l == LidButton) + result[type] = 1; + if (!result[type]) { + // INSERT HERE + } + } + return(result[type]); +} + +bool +laptop_portable::get_button(LaptopButton l) // true if a button is pressed +{ + if (::has_acpi()) { + QString name; + switch (l) { + case LidButton: + name = acpi_lid_name; + break; + case PowerButton: + name = acpi_power_name; + break; + default: + break; + } + if (!name.isEmpty()) { + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':',l,false); + if (ll[0].stripWhiteSpace() == "state") { + if (ll[1].stripWhiteSpace() == "open") { + f.close(); + return(0); + } + if (ll[1].stripWhiteSpace() == "closed") { + f.close(); + return(1); + } + break; + } + } + f.close(); + } + + } + } + if (::has_ibm() && l == LidButton) { + smapidev_sensorinfo_t t; + if (smapidev_GetSensorInfo(ibm_fd, &t) == 0) + return(t.fLidClosed != 0); + } + // INSERT HERE + return(0); +} + +#elif defined(__FreeBSD__) && HAVE_MACHINE_APM_BIOS_H + +/* +** This is the FreeBSD-specific code. +*/ + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <machine/apm_bios.h> +#include <sys/stat.h> +#include <qpushbutton.h> +#include <qobject.h> +#include <kactivelabel.h> +#include <kprocess.h> + +#define APMDEV "/dev/apm" + +// FreeBSD support by yours truly. Yay. +// Actually this code was "adapted" from apm(8) from +// FreeBSD's collection of tools. The original apm program +// was pieced together by Tatsumi Hosokawa <[email protected]> in 1994 + +// +// returns 1 if we support power management +// + +#include <iostream> +using namespace std; + +// +// something changed maybe we need to check out environment again +// +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +int +laptop_portable::has_power_management() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) { + return 0; + } + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) { + return 0; + } + + return info.ai_status; +} +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_batt_time != 0xffff); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_capabilities & 0x02); +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_capabilities & 0x01); +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux - different laptops have their own - the first here is for +// a ThinkPad] +// +int laptop_portable::has_hibernation() +{ + if (::access(PATH_TPCTL, X_OK)==0) + return(1); + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + int fd; + KActiveLabel *explain; + + fd = ::open(APMDEV, O_RDWR); + if (fd == -1) { + switch (errno) { + case ENOENT: + explain = new KActiveLabel(i18n("There is no /dev/apm file on this system. Please review the FreeBSD handbook on how to create a device node for the APM device driver (man 4 apm)."), parent); + break; + case EACCES: + explain = new KActiveLabel(i18n("Your system has the proper device node for APM support, however you cannot access it. If you are logged in as root right now, you have a problem, otherwise contact your local sysadmin and ask for read/write access to /dev/apm."), parent); + break; + case ENXIO: + explain = new KActiveLabel(i18n("Your kernel lacks support for Advanced Power Management."), parent); + break; + break; + default: + explain = new KActiveLabel(i18n("There was a generic error while opening /dev/apm."), parent); + break; + } + } else { + close(fd); + explain = new KActiveLabel(i18n("APM has most likely been disabled."), parent); + } + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + QLabel* note = new QLabel(" ", parent); + return(note); +} + + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return; + + ioctl(fd, APMIO_STANDBY, NULL); + ::close(fd); + + return; +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return; + + ioctl(fd, APMIO_SUSPEND, NULL); + ::close(fd); + + return; +} +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + KProcess thisProc; + + if (::access(PATH_TPCTL, X_OK)==0) { + thisProc << PATH_TPCTL; + thisProc << "---hibernate"; + thisProc.start(KProcess::Block); + return; + } +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +int laptop_portable::has_apm(int type) +{ + if (type == 1) // implement me .... this is the hook that pops up the panel for making /usr/sbin/apm setuid + return(0); // or in this case you could make an acpi_helper type app freebsd + return (1); +} + +void +laptop_portable::apm_set_mask(bool , bool ) +{ +} + + +// +// adds extra widgets to the battery panel +// +void +laptop_portable::extra_config(QWidget * /*parent*/, KConfig * /*config*/, QVBoxLayout * /*layout*/) +{ + // INSERT HERE +} + + + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + int ret; + + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + goto bad; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + goto bad; + + p.powered = info.ai_acline; + p.percentage = (info.ai_batt_life==255 ? 100 : info.ai_batt_life); + p.time = (info.ai_batt_time != 0xffff ? info.ai_batt_time/60 : -1); + return(p); + +bad: + p.powered = 1; + p.percentage = 100; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool /*blank*/, int /*val*/) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_performance(bool, int ¤t, QStringList &s, bool *&) // do something to help get system profiles from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); // if no profiles are available +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s, bool *&) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +bool +laptop_portable::has_software_suspend(int /*type*/) +{ + return false; // (::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool /*hibernate*/) +{ + // software_suspend_is_preferred = hibernate; +} + + +#elif defined(__NetBSD_APM__) + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <machine/apmvar.h> +#include <iostream.h> + +// +// klaptopdeamon interface to NetBSD 1.5 apm. +// Scott Presnell, [email protected], [email protected] +// Fri Jun 29 17:21:25 PDT 2001 +// Tested on Dell I4K running NetBSD 1.5R +// +#define APMDEV "/dev/apm" + +// +// Check for apm in kernel by talking to /dev/apm +// (opening read only is allowed by any process). +// returns 1 if we support power management +// +int +laptop_portable::has_power_management() +{ + int ret, fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) { + return 0; + } + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) { + return 0; + } + + return 1; +} + +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + int ret, fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) + return 0; + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.minutes_left != 0xffff); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (ust check to see if we have the binary) +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + + struct stat s; + if (stat("/usr/sbin/apm", &s)) + return(0); + return(1); +} + +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (just check to see if we have the binary) +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + + struct stat s; + if (stat("/usr/sbin/apm", &s)) + return(0); + return(1); +} + +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux - different laptops have their own - the first here is for +// a ThinkPad] +// No support in NetBSD at this time. +// +int laptop_portable::has_hibernation() +{ + // INSERT HERE + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + int fd; + KActiveLabel *explain; + + fd = ::open(APMDEV, O_RDONLY); + if (fd == -1) { + switch (errno) { + case ENOENT: + explain = new KActiveLabel(i18n("There is no /dev/apm file on this system. Please review the NetBSD documentation on how to create a device node for the APM device driver (man 4 apm)."), parent); + break; + case EACCES: + explain = new KActiveLabel(i18n("Your system has the proper device node for APM support, however you cannot access it. If you have APM compiled into the kernel this should not happen."), parent); + break; + case ENXIO: + explain = new KActiveLabel(i18n("Your kernel lacks support for Advanced Power Management."), parent); + break; + break; + default: + explain = new KActiveLabel(i18n("There was a generic error while opening /dev/apm."), parent); + break; + } + } else { + close(fd); + explain = new KActiveLabel(i18n("APM has most likely been disabled."), parent); + } + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + // INSERT HERE + QLabel* note = new QLabel(" ", parent); + return(note); +} + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + // INSERT HERE + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} + +// +// puts us into standby mode +// Use apm rather than ioctls in case they are running apmd +// (as they should be). +// +void laptop_portable::invoke_standby() +{ + KProcess proc; + proc << "/usr/sbin/apm"; + proc << "-S"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into suspend mode +// Use apm rather than ioctls in case they are running apmd +// (as they should be). +// +void laptop_portable::invoke_suspend() +{ + KProcess proc; + proc << "/usr/sbin/apm"; + proc << "-z"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into hibernate mode +// No hibernate mode for NetBSD. +// +void laptop_portable::invoke_hibernation() +{ + // INSERT HERE + return; +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +int laptop_portable::has_apm(int type) +{ + if (type == 1) // implement me .... this is the hook that pops up the panel for making /usr/sbin/apm setuid + return(0); + return (1); +} + +void +laptop_portable::apm_set_mask(bool , bool ) +{ +} + + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + int ret; + + int fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) + goto bad; + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) + goto bad; + + p.powered = (info.ac_state == APM_AC_ON); + p.percentage = (info.battery_life==255 ? 100 : info.battery_life); + p.time = (info.minutes_left != 0xffff ? info.minutes_left : -1); + return(p); + +bad: + p.powered = 1; + p.percentage = 100; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +#else + +/* +** This is utterly generic code. +*/ + +// +// something changed maybe we need to check out environment again +// +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +// +// returns 1 if we support power management +// +int +laptop_portable::has_power_management() +{ + // INSERT HERE + return(0); +} + +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + // INSERT HERE + return (0); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + // INSERT HERE + return(0); +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + // INSERT HERE + return(0); +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux] +// +int laptop_portable::has_hibernation() +{ + // INSERT HERE + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + KActiveLabel* explain = new KActiveLabel(i18n("Your computer or operating system is not supported by the current version of the\nKDE laptop control panels. If you want help porting these panels to work with it\nplease contact [email protected]."), parent); + // INSERT HERE + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + QLabel* note = new QLabel(" ", parent); + // INSERT HERE + return(note); +} + + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + // INSERT HERE + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + // INSERT HERE +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + // INSERT HERE +} +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + // INSERT HERE +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +void +laptop_portable::apm_set_mask(bool, bool) +{ + // INSERT HERE +} + +int laptop_portable::has_apm(int) +{ + // INSERT HERE + return (0); +} + + +// +// adds extra widgets to the battery panel +// +void +laptop_portable::extra_config(QWidget *parent, KConfig *config, QVBoxLayout *layout) +{ + // INSERT HERE +} + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + // INSERT HERE + p.powered = 0; + p.percentage = 0; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_performance(bool, int ¤t, QStringList &s, bool *&) // do something to help get system profiles from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); // if no profiles are available +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s, bool *&) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +bool +laptop_portable::has_software_suspend(int type) +{ + return false; // (::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool hibernate) +{ + // software_suspend_is_preferred = hibernate; +} +#endif diff --git a/klaptopdaemon/portable.h b/klaptopdaemon/portable.h new file mode 100644 index 0000000..62d325c --- /dev/null +++ b/klaptopdaemon/portable.h @@ -0,0 +1,147 @@ +#include <qlabel.h> +#include <kactivelabel.h> +#include <kconfig.h> +#include <qvgroupbox.h> +#include <qstringlist.h> + +#ifndef PORTABLE_H +#define PORTABLE_H +/* + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +struct power_result { + int powered ; // true if we're plugged into the wall + int percentage; // value 0-100 percentage of battery left + int time; // time in minutes left - -1 if this is not supported by the BIOS +}; + + +// ATTENTION: if you change something in here, please update ALL of the +// ported sections in the implementation file! + +class KDE_EXPORT laptop_portable { +public: + static void power_management_restart(); // reset internal state + static int has_power_management(); // returns 1 if this computer has power management + static int has_battery_time(); // returns 1 if this give BIOS battery time info + + /** + * Returns 1 if this computer can perform a suspend, i.e. supports some kind + * of suspend-to-ram energy saving mode (average wakeup time and energy + * saving). + */ + static int has_suspend(); + + /** + * Returns 1 if this computer can perform a standby, i.e. supports an energy + * saving mode with a very fast wakeup time (neither suspend-to-disk nor + * suspend-to-ram). + */ + static int has_standby(); + + /** + * Returns 1 if this computer can perform hibernatation, i.e. supports some + * kind of suspend-to-disk energy saving mode (highest energy saving, + * slowest wakeup time). + */ + static int has_hibernation(); + + static int has_apm(int); // returns 1 if this computer has linux-style apm of some particular type + static int has_apm() { return has_apm(0); } // returns 1 if this computer has linux-style apm + static int has_acpi(int); // returns 1 if this computer has linux-style acpi of some particular type + static int has_acpi() { return has_acpi(0); } // returns 1 if this computer has linux-style acpi + static bool has_software_suspend(int type); // // returns 1 if the system has software suspend available + static bool has_software_suspend() { return has_software_suspend(0); } + static int has_cpufreq(); // returns 1 if this computer can scale the cpu frequency + static int has_brightness(); // returns 1 if this computer can set tyhe back panel brightness + static void set_brightness(bool blank, int val); // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), + static int get_brightness(); // returns 0-255 brightness, -1 if you can't + static QString cpu_frequency(); // Returns the cpu freq. + static KActiveLabel *no_power_management_explanation(QWidget *parent); + static QLabel *how_to_do_suspend_resume(QWidget *parent); + static QLabel *pcmcia_info(int x, QWidget *parent); + + /** + * Put this computer into standby mode. + * @see has_standby() + */ + static void invoke_standby(); + + /** + * Put this computer into suspend mode. + * @see has_suspend() + */ + static void invoke_suspend(); + + /** + * Put this computer into hibernatation mode. + * @see has_hibernation() + */ + static void invoke_hibernation(); + + static struct power_result poll_battery_state(); + static void get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values); // get multiple battery status + static bool has_lav(); // true if the following returns a valid value + static float get_load_average(); // current short term load average + static void extra_config(QWidget *parent, KConfig *config, QVBoxLayout *layout); + static void acpi_set_mask(bool standby, bool suspend, bool hibernate, bool perf, bool throttle); + static void apm_set_mask(bool standby, bool suspend); + static void software_suspend_set_mask(bool hibernate); + + /** + * Get a list of available performance profiles. + * @param force - Force re-evaluation or use cached values. + * @param current - Index of the currently active profile. + * @param s - A list of available profiles. + * @param active - Marks profiles as enabled or disabled (used e.g. for ACPI + * limits). + * @return True if this system provides performance profiles. + */ + static bool get_system_performance(bool force, int ¤t, QStringList &s, bool *&active); + + /** + * Set performance profile. + * @param val - Name of the performance profile as provided by + * get_system_performance(). + */ + static void set_system_performance(QString val); + + /** + * Get a list of available throttling levels. + * @param force - Force re-evaluation or use cached values. + * @param current - Index of the currently active throttling level. + * @param s - A list of available throttling levels. + * @param active - Marks throttling labels as enabled or disabled (used e.g. + * for ACPI limits). + * @return True if this system provides throttling levels. + */ + static bool get_system_throttling(bool force, int ¤t, QStringList &s, bool *&active); + + /** + * Set throttling level. + * @param val - Name of the throttling level as provided by + * get_system_throttling(). + */ + static void set_system_throttling(QString val); + + enum LaptopButton {LidButton=0, PowerButton}; + static bool has_button(LaptopButton p); // true if we have support for a particular button + static bool get_button(LaptopButton p); // true if a button is pressed +}; + +#endif diff --git a/klaptopdaemon/power.cpp b/klaptopdaemon/power.cpp new file mode 100644 index 0000000..2477cee --- /dev/null +++ b/klaptopdaemon/power.cpp @@ -0,0 +1,587 @@ +/* + * power.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "power.h" +#include "portable.h" +#include "version.h" + +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <knumvalidator.h> +#include <kdialog.h> +#include <kapplication.h> +#include <kcombobox.h> +#include <knuminput.h> + +#include <qlayout.h> +#include <qvbuttongroup.h> +#include <qspinbox.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qslider.h> +#include <qtooltip.h> +extern void wake_laptop_daemon(); + +PowerConfig::PowerConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + nopowerBox(0), + nopowerStandby(0), + nopowerSuspend(0), + nopowerOff(0), + nopowerHibernate(0), + nopowerBrightness(0), + nopowerValBrightness(0), + nopowerThrottle(0), + nopowerValThrottle(0), + nopowerPerformance(0), + nopowerValPerformance(0), + + powerBox(0), + powerStandby(0), + powerSuspend(0), + powerOff(0), + powerHibernate(0), + powerBrightness(0), + powerValBrightness(0), + powerThrottle(0), + powerValThrottle(0), + powerPerformance(0), + powerValPerformance(0), + + + noeditwait(0), + editwait(0), + enablelav(0), + noenablelav(0), + noeditlav(0), + editlav(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + int can_brightness = laptop_portable::has_brightness(); + QStringList throttle_list; + int current_throttle; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + QStringList performance_list; + int current_performance; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + + if (!apm && !can_brightness && !has_throttle && !has_performance) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + + if (!can_standby && !can_suspend && !can_hibernate && !can_brightness && !has_throttle && !has_performance) + apm = 0; + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + QLabel* explain = laptop_portable::how_to_do_suspend_resume(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + QHBoxLayout *hlay = new QHBoxLayout( top_layout ); + + nopowerBox = new QVButtonGroup(i18n("Not Powered"), this); + QToolTip::add( nopowerBox, i18n( "Options in this box apply when the laptop is unplugged from the wall and has been idle for a while" ) ); + nopowerBox->layout()->setSpacing( KDialog::spacingHint() ); + hlay->addWidget( nopowerBox ); + + if (can_standby) { + nopowerStandby = new QRadioButton(i18n("Standb&y"), nopowerBox); + QToolTip::add( nopowerStandby, i18n( "Causes the laptop to change to a standby temporary-low power state" ) ); + } + if (can_suspend) { + nopowerSuspend = new QRadioButton(i18n("&Suspend"), nopowerBox); + QToolTip::add( nopowerSuspend, i18n( "Causes the laptop to change to a suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + nopowerHibernate = new QRadioButton(i18n("H&ibernate"), nopowerBox); + QToolTip::add( nopowerHibernate, i18n( "Causes the laptop to change to a hibernate 'save-to-disk' state" ) ); + } + if (can_suspend||can_standby||can_hibernate) + nopowerOff = new QRadioButton(i18n("None"), nopowerBox); + if (can_brightness) { + nopowerBrightness = new QCheckBox(i18n("Brightness"), nopowerBox); + QToolTip::add( nopowerBrightness, i18n( "Enables changing the laptop's back panel brightness" ) ); + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + nopowerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( nopowerValBrightness, i18n( "How bright to change the back panel" ) ); + nopowerValBrightness->setEnabled(0); + connect(nopowerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(nopowerBrightness, SIGNAL(toggled(bool)), nopowerValBrightness, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + nopowerPerformance = new QCheckBox(i18n("System performance"), nopowerBox); + QToolTip::add( nopowerPerformance, i18n( "Enables changing the laptop's performance profile" ) ); + + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + nopowerValPerformance = new KComboBox(0, wp); + QToolTip::add( nopowerValPerformance, i18n( "Which profile to change it to" ) ); + nopowerValPerformance->insertStringList(performance_list); + nopowerValPerformance->setEnabled(0); + connect(nopowerValPerformance, SIGNAL(activated(int)), this, SLOT(changed())); + connect(nopowerPerformance, SIGNAL(toggled(bool)), nopowerValPerformance, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + nopowerThrottle = new QCheckBox(i18n("CPU throttle"), nopowerBox); + QToolTip::add( nopowerThrottle, i18n( "Enables throttling the laptop's CPU" ) ); + + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + nopowerValThrottle = new KComboBox(0, wp); + QToolTip::add( nopowerValThrottle, i18n( "How much to throttle the laptop's CPU" ) ); + nopowerValThrottle->insertStringList(throttle_list); + nopowerValThrottle->setEnabled(0); + connect(nopowerValThrottle, SIGNAL(activated(int)), this, SLOT(changed())); + connect(nopowerThrottle, SIGNAL(toggled(bool)), nopowerValThrottle, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValThrottle); + xl->addStretch(1); + } + + + connect(nopowerBox, SIGNAL(clicked(int)), this, SLOT(changed())); + + bool can_lav = laptop_portable::has_lav(); + QHBox *hbox; + if (can_lav) { + hbox = new QHBox( nopowerBox ); + noenablelav = new QCheckBox(i18n("Don't act if LAV is >"), hbox); + connect(noenablelav, SIGNAL(clicked()), this, SLOT(changed())); + noeditlav = new KDoubleSpinBox(0.0, 10.0, 0.0, 0.1, 1, hbox); + QToolTip::add( noeditlav, i18n( "If enabled and the system load average is greater than this value none of the above options will be applied" ) ); + connect(noeditlav, SIGNAL(valueChanged(double)), this, SLOT(changed())); + connect(noenablelav, SIGNAL(toggled(bool)), noeditlav, SLOT(setEnabled(bool))); + } + + hbox = new QHBox( nopowerBox ); + QLabel* noedlabel = new QLabel(i18n("&Wait for:"), hbox); + noeditwait = new QSpinBox( 1, 60*24 /*1 day*/, 1, hbox ); + QToolTip::add( noeditwait, i18n( "How long the computer has to be idle before these values take effect" ) ); + noeditwait->setSuffix( i18n("keep short, unit in spinbox", "min") ); + noedlabel->setBuddy( noeditwait ); + hbox->setStretchFactor( noeditwait, 1 ); + connect( noeditwait, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + + /////////////////////////////////////////////////////////////// + + + powerBox = new QVButtonGroup(i18n("Powered"), this); + powerBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( powerBox, i18n( "Options in this box apply when the laptop is plugged into the wall and has been idle for a while" ) ); + hlay->addWidget( powerBox ); + + if (can_standby) { + powerStandby = new QRadioButton(i18n("Sta&ndby"), powerBox); + QToolTip::add( powerStandby, i18n( "Causes the laptop to change to a standby temporary-low power state" ) ); + } + if (can_suspend) { + powerSuspend = new QRadioButton(i18n("S&uspend"), powerBox); + QToolTip::add( powerSuspend, i18n( "Causes the laptop to change to a suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + powerHibernate = new QRadioButton(i18n("Hi&bernate"), powerBox); + QToolTip::add( powerHibernate, i18n( "Causes the laptop to change to a hibernate 'save-to-disk' state" ) ); + } + if (can_suspend||can_standby||can_hibernate) + powerOff = new QRadioButton(i18n("None"), powerBox); + if (can_brightness) { + powerBrightness = new QCheckBox(i18n("Brightness"), powerBox); + QToolTip::add( powerBrightness, i18n( "Enables changing the laptop's back panel brightness" ) ); + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + powerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( powerValBrightness, i18n( "How bright to change the back panel" ) ); + powerValBrightness->setEnabled(0); + connect(powerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(powerBrightness, SIGNAL(toggled(bool)), powerValBrightness, SLOT(setEnabled(bool))); + xl->addWidget(powerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + powerPerformance = new QCheckBox(i18n("System performance"), powerBox); + QToolTip::add( powerPerformance, i18n( "Enables changing the laptop's performance profile" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValPerformance = new KComboBox(0, wp); + QToolTip::add( powerValPerformance, i18n( "Which profile to change it to" ) ); + powerValPerformance->insertStringList(performance_list); + powerValPerformance->setEnabled(0); + connect(powerValPerformance, SIGNAL(activated(int)), this, SLOT(changed())); + connect(powerPerformance, SIGNAL(toggled(bool)), powerValPerformance, SLOT(setEnabled(bool))); + xl->addWidget(powerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + powerThrottle = new QCheckBox(i18n("CPU throttle"), powerBox); + QToolTip::add( powerThrottle, i18n( "Enables throttling the laptop's CPU" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValThrottle = new KComboBox(0, wp); + QToolTip::add( powerValThrottle, i18n( "How much to throttle the laptop's CPU" ) ); + powerValThrottle->insertStringList(throttle_list); + powerValThrottle->setEnabled(0); + connect(powerValThrottle, SIGNAL(activated(int)), this, SLOT(changed())); + connect(powerThrottle, SIGNAL(toggled(bool)), powerValThrottle, SLOT(setEnabled(bool))); + xl->addWidget(powerValThrottle); + xl->addStretch(1); + } + + connect(powerBox, SIGNAL(clicked(int)), this, SLOT(changed())); + + if (can_lav) { + hbox = new QHBox( powerBox ); + enablelav = new QCheckBox(i18n("Don't act if LAV is >"), hbox); + connect( enablelav, SIGNAL(clicked()), this, SLOT(changed())); + editlav = new KDoubleSpinBox(0.0, 10.0, 0.0, 0.1, 1, hbox); + QToolTip::add( editlav, i18n( "If enabled and the system load average is greater than this value none of the above options will be applied" ) ); + connect( editlav, SIGNAL(valueChanged(double)), this, SLOT(changed())); + connect( enablelav, SIGNAL(toggled(bool)), editlav, SLOT(setEnabled(bool)) ); + } + + hbox = new QHBox( powerBox ); + QLabel* edlabel = new QLabel(i18n("Wai&t for:"), hbox); + editwait = new QSpinBox( 1, 60*24 /*1 day*/, 1, hbox ); + QToolTip::add( editwait, i18n( "How long the computer has to be idle before these values take effect" ) ); + editwait->setSuffix( i18n("keep short, unit in spinbox", "min") ); + edlabel->setBuddy( editwait ); + hbox->setStretchFactor( editwait, 1 ); + connect( editwait, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + hlay->addStretch(1); + + QLabel* explain = new QLabel(i18n("This panel configures the behavior of the automatic power-down feature - " + "it works as a sort of extreme screen saver. You can configure different " + "timeouts and types of behavior depending on whether or not your laptop is " + "plugged in to the mains supply."), this ); + explain->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain); + + if (can_standby) { + QLabel* explain3 = new QLabel(i18n("Different laptops may respond to 'standby' in different ways - in many " + "it is only a temporary state and may not be useful for you."), this); + explain3->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain3, 0, Qt::AlignLeft); + } + + top_layout->addStretch(1); + + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this ), 0, Qt::AlignRight ); + } + } + + load(); +} + +PowerConfig::~PowerConfig() +{ + delete config; +} + +void PowerConfig::save() +{ + if (editwait) { + power = getPower(); + nopower = getNoPower(); + edit_wait = editwait->value(); + noedit_wait = noeditwait->value(); + nopower_bright_enabled = (nopowerBrightness?nopowerBrightness->isChecked():0); + power_bright_enabled = (powerBrightness?powerBrightness->isChecked():0); + nopower_bright_val = (nopowerValBrightness?nopowerValBrightness->value():0); + power_bright_val = (powerValBrightness?powerValBrightness->value():255); + nopower_performance_enabled = (nopowerPerformance?nopowerPerformance->isChecked():0); + power_performance_enabled = (powerPerformance?powerPerformance->isChecked():0); + nopower_performance_val = (nopowerValPerformance?nopowerValPerformance->currentText():""); + power_performance_val = (powerValPerformance?powerValPerformance->currentText():""); + nopower_throttle_enabled = (nopowerThrottle?nopowerThrottle->isChecked():0); + power_throttle_enabled = (powerThrottle?powerThrottle->isChecked():0); + nopower_throttle_val = (nopowerValThrottle?nopowerValThrottle->currentText():""); + power_throttle_val = (powerValThrottle?powerValThrottle->currentText():""); + edit_lav = (editlav?editlav->value():-1); + noedit_lav = (noeditlav?noeditlav->value():-1); + lav_enabled = (enablelav?enablelav->isChecked():0); + nolav_enabled = (noenablelav?noenablelav->isChecked():0); + } + + config->setGroup("LaptopPower"); + config->writeEntry("NoPowerSuspend", nopower); + config->writeEntry("PowerSuspend", power); + config->writeEntry("PowerWait", edit_wait); + config->writeEntry("NoPowerWait", noedit_wait); + config->writeEntry("PowerLav", edit_lav); + config->writeEntry("NoPowerLav", noedit_lav); + config->writeEntry("LavEnabled", lav_enabled); + config->writeEntry("NoLavEnabled", nolav_enabled); + config->writeEntry("PowerBrightnessEnabled", power_bright_enabled); + config->writeEntry("NoPowerBrightnessEnabled", nopower_bright_enabled); + config->writeEntry("PowerBrightness", power_bright_val); + config->writeEntry("NoPowerBrightness", nopower_bright_val); + config->writeEntry("PowerPerformanceEnabled", power_performance_enabled); + config->writeEntry("NoPowerPerformanceEnabled", nopower_performance_enabled); + config->writeEntry("PowerPerformance", power_performance_val); + config->writeEntry("NoPowerPerformance", nopower_performance_val); + config->writeEntry("PowerThrottleEnabled", power_throttle_enabled); + config->writeEntry("NoPowerThrottleEnabled", nopower_throttle_enabled); + config->writeEntry("PowerThrottle", power_throttle_val); + config->writeEntry("NoPowerThrottle", nopower_throttle_val); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void PowerConfig::load() +{ + load( false ); +} + +void PowerConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("LaptopPower"); + nopower = config->readNumEntry("NoPowerSuspend", (nopowerStandby?1:nopowerSuspend?2:0)); + power = config->readNumEntry("PowerSuspend", 0); + edit_wait = config->readNumEntry("PowerWait", 20); + noedit_wait = config->readNumEntry("NoPowerWait", 5); + edit_lav = config->readDoubleNumEntry("PowerLav", -1); + noedit_lav = config->readDoubleNumEntry("NoPowerLav", -1); + lav_enabled = config->readBoolEntry("LavEnabled", 0); + nolav_enabled = config->readBoolEntry("NoLavEnabled", 0); + nopower_bright_enabled = config->readBoolEntry("NoPowerBrightnessEnabled", 0); + power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0); + nopower_bright_val = config->readNumEntry("NoPowerBrightness", 0); + power_bright_val = config->readNumEntry("PowerBrightness", 255); + nopower_performance_enabled = config->readBoolEntry("NoPowerPerformanceEnabled", 0); + power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0); + nopower_performance_val = config->readEntry("NoPowerPerformance", ""); + power_performance_val = config->readEntry("PowerPerformance", ""); + nopower_throttle_enabled = config->readBoolEntry("NoPowerThrottleEnabled", 0); + power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0); + nopower_throttle_val = config->readEntry("NoPowerThrottle", ""); + power_throttle_val = config->readEntry("PowerThrottle", ""); + + // the GUI should reflect the real values + if (editwait) { + editwait->setValue(edit_wait); + noeditwait->setValue(noedit_wait); + if (editlav) { + editlav->setValue(edit_lav); + editlav->setEnabled(lav_enabled); + } + if (noeditlav) { + noeditlav->setValue(noedit_lav); + noeditlav->setEnabled(nolav_enabled); + } + if (enablelav) + enablelav->setChecked(lav_enabled); + if (noenablelav) + noenablelav->setChecked(nolav_enabled); + setPower(power, nopower); + if (nopowerBrightness) + nopowerBrightness->setChecked(nopower_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (nopowerValBrightness) { + nopowerValBrightness->setValue(nopower_bright_val); + nopowerValBrightness->setEnabled(nopower_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + if (nopowerPerformance) + nopowerPerformance->setChecked(nopower_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (nopowerValPerformance) { + int ind = 0; + for (int i = 0; i < nopowerValPerformance->count(); i++) + if (nopowerValPerformance->text(i) == nopower_performance_val) { + ind = i; + break; + } + nopowerValPerformance->setCurrentItem(ind); + nopowerValPerformance->setEnabled(nopower_performance_enabled); + } + if (powerValPerformance) { + int ind = 0; + for (int i = 0; i < powerValPerformance->count(); i++) + if (powerValPerformance->text(i) == power_performance_val) { + ind = i; + break; + } + powerValPerformance->setCurrentItem(ind); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (nopowerThrottle) + nopowerThrottle->setChecked(nopower_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (nopowerValThrottle) { + int ind = 0; + for (int i = 0; i < nopowerValThrottle->count(); i++) + if (nopowerValThrottle->text(i) == nopower_throttle_val) { + ind = i; + break; + } + nopowerValThrottle->setCurrentItem(ind); + nopowerValThrottle->setEnabled(nopower_throttle_enabled); + } + if (powerValThrottle) { + int ind = 0; + for (int i = 0; i < powerValThrottle->count(); i++) + if (powerValThrottle->text(i) == power_throttle_val) { + ind = i; + break; + } + powerValThrottle->setCurrentItem(ind); + powerValThrottle->setEnabled(power_throttle_enabled); + } + } + emit changed( useDefaults ); +} + +void PowerConfig::defaults() +{ + load( true ); +} + +int PowerConfig::getNoPower() +{ + if (!apm) + return(nopower); + if (nopowerHibernate && nopowerHibernate->isChecked()) + return 3; + if (nopowerStandby && nopowerStandby->isChecked()) + return 1; + if (nopowerSuspend && nopowerSuspend->isChecked()) + return 2; + return(0); +} + +int PowerConfig::getPower() +{ + if (!apm || !powerOff) + return(power); + if (powerHibernate && powerHibernate->isChecked()) + return 3; + if (powerStandby && powerStandby->isChecked()) + return 1; + if (powerSuspend && powerSuspend->isChecked()) + return 2; + return(0); +} + +void PowerConfig::setPower(int p, int np) +{ + if (!apm || nopowerOff == 0) + return; + if (nopowerSuspend) { + nopowerSuspend->setChecked(FALSE); + } else { + if (np == 2) np = 0; + } + if (nopowerStandby) { + nopowerStandby->setChecked(FALSE); + } else { + if (np == 1) np = 0; + } + if (nopowerHibernate) { + nopowerHibernate->setChecked(FALSE); + } else { + if (np == 3) np = 0; + } + if (nopowerOff) + nopowerOff->setChecked(FALSE); + switch (np) { + case 0: nopowerOff->setChecked(TRUE);break; + case 1: nopowerStandby->setChecked(TRUE);break; + case 2: nopowerSuspend->setChecked(TRUE);break; + case 3: nopowerHibernate->setChecked(TRUE);break; + } + if (powerSuspend) { + powerSuspend->setChecked(FALSE); + } else { + if (p == 2) p = 0; + } + if (powerStandby) { + powerStandby->setChecked(FALSE); + } else { + if (p == 1) p = 0; + } + if (powerHibernate) { + powerHibernate->setChecked(FALSE); + } else { + if (p == 3) p = 0; + } + if (powerOff) + powerOff->setChecked(FALSE); + switch (p) { + case 0: powerOff->setChecked(TRUE);break; + case 1: powerStandby->setChecked(TRUE);break; + case 2: powerSuspend->setChecked(TRUE);break; + case 3: powerHibernate->setChecked(TRUE);break; + } +} + + +QString PowerConfig::quickHelp() const +{ + return i18n("<h1>Laptop Power Control</h1>This module allows you to " + "control the power settings of your laptop and set timouts that will trigger " + "state changes you can use to save power"); + +} + +#include "power.moc" diff --git a/klaptopdaemon/power.h b/klaptopdaemon/power.h new file mode 100644 index 0000000..0d9d624 --- /dev/null +++ b/klaptopdaemon/power.h @@ -0,0 +1,98 @@ +/* + * power.h + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __POWERCONFIG_H__ +#define __POWERCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSlider; +class QButtonGroup; +class QRadioButton; +class QSpinBox; +class KConfig; +class QCheckBox; +class KComboBox; +class KDoubleSpinBox; + +class PowerConfig : public KCModule +{ + Q_OBJECT +public: + PowerConfig( QWidget *parent=0, const char* name=0); + ~PowerConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + + +private: + + int getPower(); + int getNoPower(); + void setPower( int, int ); + + QButtonGroup *nopowerBox; + QRadioButton *nopowerStandby, *nopowerSuspend, *nopowerOff, *nopowerHibernate; + QCheckBox *nopowerBrightness; + QSlider *nopowerValBrightness; + QCheckBox *nopowerThrottle; + KComboBox *nopowerValThrottle; + QCheckBox *nopowerPerformance; + KComboBox *nopowerValPerformance; + QButtonGroup *powerBox; + QRadioButton *powerStandby, *powerSuspend, *powerOff, *powerHibernate; + QCheckBox *powerBrightness; + QSlider *powerValBrightness; + QCheckBox *powerThrottle; + KComboBox *powerValThrottle; + QCheckBox *powerPerformance; + KComboBox *powerValPerformance; + QSpinBox *noeditwait; + QSpinBox *editwait; + QCheckBox *enablelav; + QCheckBox *noenablelav; + KDoubleSpinBox *noeditlav; + KDoubleSpinBox *editlav; + int edit_wait, noedit_wait; + int power_bright_val, nopower_bright_val; + bool nopower_bright_enabled, power_bright_enabled; + bool nopower_throttle_enabled, power_throttle_enabled; + QString nopower_throttle_val, power_throttle_val; + bool nopower_performance_enabled, power_performance_enabled; + bool lav_enabled, nolav_enabled; + float edit_lav, noedit_lav; + QString nopower_performance_val, power_performance_val; + + KConfig *config; + int power, nopower, apm; +}; + +#endif + diff --git a/klaptopdaemon/profile.cpp b/klaptopdaemon/profile.cpp new file mode 100644 index 0000000..a6285cb --- /dev/null +++ b/klaptopdaemon/profile.cpp @@ -0,0 +1,424 @@ +/* + * brightness.cpp + * + * Copyright (c) 2003 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "profile.h" +#include "version.h" +#include "portable.h" + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +// other KDE headers: +#include <klocale.h> +#include <kconfig.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <kcombobox.h> + +// other Qt headers: +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qgrid.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtooltip.h> + +extern void wake_laptop_daemon(); + +ProfileConfig::ProfileConfig(QWidget * parent, const char *name) + : KCModule(parent, name) +{ + QStringList performance_list; + int current_performance; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QHBoxLayout *ll = new QHBoxLayout(); + + QVGroupBox *gb = new QVGroupBox(i18n("Not Powered"), this); + QToolTip::add( gb, i18n( "Items in this box take effect whenever the laptop is unplugged from the wall" ) ); + if (laptop_portable::has_brightness()) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + poff = new QCheckBox(i18n("Back panel brightness"), wp); + QToolTip::add( poff, i18n( "Enables the changing of the back panel brightness" ) ); + xl->addWidget(poff); + connect (poff, SIGNAL(toggled(bool)), this, SLOT(poff_changed(bool))); + + xl->addWidget(new QLabel("-", wp)); + soff = new QSlider(0, 255, 16, 160, Qt::Horizontal, wp); + soff->setEnabled(0); + QToolTip::add( soff, i18n( "How bright it should be when it is changed" ) ); + connect (soff, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(soff); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } else { + poff = 0; + soff = 0; + } + + if (has_performance) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + performance_off = new QCheckBox(i18n("System performance"), wp); + QToolTip::add( performance_off, i18n( "Enables the changing of the system performance profile" ) ); + xl->addWidget(performance_off); + connect (performance_off, SIGNAL(toggled(bool)), this, SLOT(performance_off_changed(bool))); + + performance_val_off = new KComboBox(0, wp); + QToolTip::add( performance_val_off, i18n( "The new system performance profile to change to" ) ); + performance_val_off->insertStringList(performance_list); + performance_val_off->setEnabled(0); + connect (performance_val_off, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(performance_val_off); + xl->addStretch(1); + } else { + performance_off = 0; + performance_val_off = 0; + } + if (has_throttle) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + throttle_off = new QCheckBox(i18n("CPU throttling"), wp); + QToolTip::add( throttle_off, i18n( "Enables the throttling of the CPU performance" ) ); + xl->addWidget(throttle_off); + connect (throttle_off, SIGNAL(toggled(bool)), this, SLOT(throttle_off_changed(bool))); + + throttle_val_off = new KComboBox(0, wp); + throttle_val_off->insertStringList(throttle_list); + throttle_val_off->setEnabled(0); + QToolTip::add( throttle_val_off, i18n( "How much to throttle the CPU by" ) ); + connect (throttle_val_off, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(throttle_val_off); + xl->addStretch(1); + } else { + throttle_off = 0; + throttle_val_off = 0; + } + + ll->addWidget(gb); + + gb = new QVGroupBox(i18n("Powered"), this); + QToolTip::add( gb, i18n( "Items in this box take effect whenever the laptop is plugged into the wall" ) ); + if (laptop_portable::has_brightness()) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + pon = new QCheckBox(i18n("Back panel brightness"), wp); + QToolTip::add( pon, i18n( "Enables the changing of the back panel brightness" ) ); + xl->addWidget(pon); + connect (pon, SIGNAL(toggled(bool)), this, SLOT(pon_changed(bool))); + + xl->addWidget(new QLabel("-", wp)); + son = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + son->setEnabled(0); + QToolTip::add( son, i18n( "How bright it should be when it is changed" ) ); + connect (son, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(son); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } else { + pon = 0; + son = 0; + } + if (has_performance) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + performance_on = new QCheckBox(i18n("System performance"), wp); + QToolTip::add( performance_on, i18n( "Enables the changing of the system performance profile" ) ); + xl->addWidget(performance_on); + connect (performance_on, SIGNAL(toggled(bool)), this, SLOT(performance_on_changed(bool))); + + performance_val_on = new KComboBox(0, wp); + performance_val_on->insertStringList(performance_list); + performance_val_on->setEnabled(0); + QToolTip::add( performance_val_on, i18n( "The new system performance profile to change to" ) ); + connect (performance_val_on, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(performance_val_on); + xl->addStretch(1); + } else { + performance_on = 0; + performance_val_on = 0; + } + if (has_throttle) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + throttle_on = new QCheckBox(i18n("CPU throttle"), wp); + QToolTip::add( throttle_on, i18n( "Enables the throttling of the CPU performance" ) ); + xl->addWidget(throttle_on); + connect (throttle_on, SIGNAL(toggled(bool)), this, SLOT(throttle_on_changed(bool))); + + throttle_val_on = new KComboBox(0, wp); + throttle_val_on->insertStringList(throttle_list); + throttle_val_on->setEnabled(0); + QToolTip::add( throttle_val_on, i18n( "How much to throttle the CPU by" ) ); + connect (throttle_val_on, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(throttle_val_on); + xl->addStretch(1); + } else { + throttle_on = 0; + throttle_val_on = 0; + } + ll->addWidget(gb); + + ll->addStretch(1); + + top_layout->addLayout(ll); + QLabel *tmp_label = new QLabel(i18n("This panel allows you to set default values for system attributes " + "so that they change when the laptop is plugged in to the wall or " + "running on batteries."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel(i18n("You can also set options for these values that will be set by low battery " + "conditions, or system inactivity in the other panels"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +ProfileConfig::~ProfileConfig() +{ + delete config; +} + +void ProfileConfig::pon_changed(bool v) +{ + if (son) + son->setEnabled(v); + configChanged(); +} + +void ProfileConfig::poff_changed(bool v) +{ + if (soff) + soff->setEnabled(v); + configChanged(); +} + +void ProfileConfig::performance_on_changed(bool v) +{ + if (performance_val_on) + performance_val_on->setEnabled(v); + configChanged(); +} + +void ProfileConfig::performance_off_changed(bool v) +{ + if (performance_val_off) + performance_val_off->setEnabled(v); + configChanged(); +} + +void ProfileConfig::throttle_on_changed(bool v) +{ + if (throttle_val_on) + throttle_val_on->setEnabled(v); + configChanged(); +} + +void ProfileConfig::throttle_off_changed(bool v) +{ + if (throttle_val_off) + throttle_val_off->setEnabled(v); + configChanged(); +} + + +void ProfileConfig::save() +{ + config->setGroup("ProfileDefault"); + + config->writeEntry("EnableBrightnessOn", (pon?pon->isChecked():0)); + config->writeEntry("BrightnessOnLevel", (son?son->value():255)); + config->writeEntry("EnableBrightnessOff", (poff?poff->isChecked():0)); + config->writeEntry("BrightnessOffLevel", (soff?soff->value():160)); + config->writeEntry("EnablePerformanceOn", (performance_on?performance_on->isChecked():0)); + config->writeEntry("PerformanceOnLevel", (performance_val_on?performance_val_on->currentText():"")); + config->writeEntry("EnablePerformanceOff", (performance_off?performance_off->isChecked():0)); + config->writeEntry("PerformanceOffLevel", (performance_val_off?performance_val_off->currentText():"")); + config->writeEntry("EnableThrottleOn", (throttle_on?throttle_on->isChecked():0)); + config->writeEntry("ThrottleOnLevel", (throttle_val_on?throttle_val_on->currentText():"")); + config->writeEntry("EnableThrottleOff", (throttle_off?throttle_off->isChecked():0)); + config->writeEntry("ThrottleOffLevel", (throttle_val_off?throttle_val_off->currentText():"")); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ProfileConfig::load() +{ + load( false ); +} + +void ProfileConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("ProfileDefault"); + + bool v; + if (pon) { + v = config->readBoolEntry("EnableBrightnessOn", false); + pon->setChecked(v); + } else { + v = 0; + } + int x; + if (son) { + x = config->readNumEntry("BrightnessOnLevel", 255); + son->setValue(x); + son->setEnabled(v); + } + if (poff) { + v = config->readBoolEntry("EnableBrightnessOff", false); + poff->setChecked(v); + } else { + v = 0; + } + if (soff) { + x = config->readNumEntry("BrightnessOffLevel", 160); + soff->setValue(x); + soff->setEnabled(v); + } + if (performance_on) { + v = config->readBoolEntry("EnablePerformanceOn", false); + performance_on->setChecked(v); + } else { + v = 0; + } + if (performance_val_on) { + QString s = config->readEntry("PerformanceOnLevel", ""); + int ind = 0; + for (int i = 0; i < performance_val_on->count(); i++) + if (performance_val_on->text(i) == s) { + ind = i; + break; + } + performance_val_on->setCurrentItem(ind); + performance_val_on->setEnabled(v); + } + if (performance_off) { + v = config->readBoolEntry("EnablePerformanceOff", false); + performance_off->setChecked(v); + } else { + v = 0; + } + if (performance_val_off) { + QString s = config->readEntry("PerformanceOffLevel", ""); + int ind = 0; + for (int i = 0; i < performance_val_off->count(); i++) + if (performance_val_off->text(i) == s) { + ind = i; + break; + } + performance_val_off->setCurrentItem(ind); + performance_val_off->setEnabled(v); + } + if (throttle_on) { + v = config->readBoolEntry("EnableThrottleOn", false); + throttle_on->setChecked(v); + } else { + v = 0; + } + if (throttle_val_on) { + QString s = config->readEntry("ThrottleOnLevel", ""); + int ind = 0; + for (int i = 0; i < throttle_val_on->count(); i++) + if (throttle_val_on->text(i) == s) { + ind = i; + break; + } + throttle_val_on->setCurrentItem(ind); + throttle_val_on->setEnabled(v); + } + if (throttle_off) { + v = config->readBoolEntry("EnableThrottleOff", false); + throttle_off->setChecked(v); + } else { + v = 0; + } + if (throttle_val_off) { + QString s = config->readEntry("ThrottleOffLevel", ""); + int ind = 0; + for (int i = 0; i < throttle_val_off->count(); i++) + if (throttle_val_off->text(i) == s) { + ind = i; + break; + } + throttle_val_off->setCurrentItem(ind); + throttle_val_off->setEnabled(v); + } + emit changed( useDefaults ); +} + +void ProfileConfig::defaults() +{ + load( true ); +} + + +void ProfileConfig::configChanged() +{ + emit changed(true); +} + + +QString ProfileConfig::quickHelp() const +{ + return i18n("<h1>Laptop Power Profile Setup</h1>This module allows you to configure default values for static laptop " + "system attributes that will change when the laptop is plugged in or unplugged from the wall."); +} + + +void ProfileConfig::slotStartMonitor() +{ + wake_laptop_daemon(); +} + + +#include "profile.moc" + + diff --git a/klaptopdaemon/profile.h b/klaptopdaemon/profile.h new file mode 100644 index 0000000..a9a81be --- /dev/null +++ b/klaptopdaemon/profile.h @@ -0,0 +1,82 @@ +/* + * brightness.h + * + * Copyright (c) 2003 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BRIGHTNESSCONFIG_H__ +#define __BRIGHTNESSCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class QSlider; +class KIconLoader; +class KIconButton; +class QPushButton; +class KComboBox; + + +class ProfileConfig : public KCModule +{ + Q_OBJECT +public: + ProfileConfig( QWidget *parent=0, const char* name=0); + ~ProfileConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void slotStartMonitor(); + void poff_changed(bool); + void pon_changed(bool); + void throttle_off_changed(bool); + void throttle_on_changed(bool); + void performance_off_changed(bool); + void performance_on_changed(bool); + + +private: + KConfig *config; + + QCheckBox *pon, *performance_on, *throttle_on; + QSlider *son; + KComboBox *performance_val_on, *throttle_val_on; + QCheckBox *poff, *performance_off, *throttle_off; + QSlider *soff; + KComboBox *performance_val_off, *throttle_val_off; + + +}; + +#endif + diff --git a/klaptopdaemon/smapi.h b/klaptopdaemon/smapi.h new file mode 100644 index 0000000..fff1285 --- /dev/null +++ b/klaptopdaemon/smapi.h @@ -0,0 +1,54 @@ + +/********************************************************************* + * + * Filename: smapi.h + * Description: header file for the smapi driver + * Author: Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPI_H__ +#define __SMAPI_H__ + +#include "smapibios.h" + + +/****** typedefs ******/ + +typedef smb_inparm_t smapi_inparm_t; +typedef smb_outparm_t smapi_outparm_t; + +typedef union _smapi_ioparm_t { + smapi_inparm_t in; + smapi_outparm_t out; +} smapi_ioparm_t; + + +/****** declarations ******/ + +int smapi_do( + unsigned long ulongIoctlArg, + flag_t fCallerHasWritePerm +); + + +#endif diff --git a/klaptopdaemon/smapibios.h b/klaptopdaemon/smapibios.h new file mode 100644 index 0000000..2751dc8 --- /dev/null +++ b/klaptopdaemon/smapibios.h @@ -0,0 +1,93 @@ + +/********************************************************************* + * + * Filename: smapibios.h + * Description: header file for the IBM SMAPI BIOS + * Author: Thomas Hood + * Created: 14 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPIBIOS_H__ +#define __SMAPIBIOS_H__ + +/* Is included by smapi.h */ + +/*** SMAPI BIOS error codes ***/ +#define ERR_SMB_MIN ((byte)0x01) +#define ERR_SMB_FUNC_NOT_AVAIL ((byte)0x53) +#define ERR_SMB_FUNC_NOT_SUPPORTED ((byte)0x86) +#define ERR_SMB_SYSTEM_ERROR ((byte)0x90) +#define ERR_SMB_SYSTEM_INVALID ((byte)0x91) +#define ERR_SMB_SYSTEM_BUSY ((byte)0x92) +#define ERR_SMB_DEVICE_ERROR ((byte)0xA0) +#define ERR_SMB_DEVICE_BUSY ((byte)0xA1) +#define ERR_SMB_DEVICE_NOT_ATTACHED ((byte)0xA2) +#define ERR_SMB_DEVICE_DISABLED ((byte)0xA3) +#define ERR_SMB_PARM_INVALID ((byte)0x81) +#define ERR_SMB_PARM_OUT_OF_RANGE ((byte)0xA4) +#define ERR_SMB_PARM_NOT_ACCEPTED ((byte)0xA5) +#define ERR_SMB_MAX ((byte)0xFF) + +/* The following structure definitions come from the ThinkPad 560Z Technical Reference */ + +/*** SMAPI BIOS header ***/ +typedef struct _smb_header { + byte bSig[4]; /* signature */ + byte bVerMajor; /* major version */ + byte bVerMinor; /* minor version */ + byte bLen; /* length */ + byte bChksum; /* checksum */ + word wInfo; /* information word */ + word wRsv1; /* reserve 1 */ + word wR_offset; /* real mode offset */ + word wR_segment; /* real mode segment */ + word wRsv2; /* reserve 2 */ + word wP16_offset; /* 16-bit protect mode offset */ + dword dwP16_base; /* 16-bit protect mode base address */ + dword dwP32_offset; /* 32-bit protect mode offset */ + dword dwP32_base; /* 32-bit protect mode base address */ +} smb_header_t; + +/*** SMAPI BIOS call input parameters ***/ +typedef struct _smb_inparm { + byte bFunc; + byte bSubFunc; + word wParm1; + word wParm2; + word wParm3; + dword dwParm4; + dword dwParm5; +} smb_inparm_t; + + +/*** SMAPI BIOS call output parameters ***/ +typedef struct _smb_outparm { + byte bRc; + byte bSubRc; + word wParm1; + word wParm2; + word wParm3; + dword dwParm4; + dword dwParm5; +} smb_outparm_t; + +#endif diff --git a/klaptopdaemon/smapidev.c b/klaptopdaemon/smapidev.c new file mode 100644 index 0000000..3dbcd6d --- /dev/null +++ b/klaptopdaemon/smapidev.c @@ -0,0 +1,743 @@ +#if defined(__linux__) || defined(__FreeBSD__) +/********************************************************************* + * + * Filename: smapidev.c + * Description: IBM SMAPI (System Management API) interface functions + * Author: Bill Mair, Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood and Bill Mair, + * All rights reserved + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#include <fcntl.h> +#include <stdlib.h> +#ifdef __linux__ +#include <linux/unistd.h> +#else +#include <unistd.h> +#endif +#include <getopt.h> +#include <sys/ioctl.h> +#include <errno.h> +#ifdef __linux__ +#include <linux/types.h> +#else +#include <sys/types.h> +#endif +#include <stdio.h> +#include <string.h> + +#ifndef __linux__ +typedef uint8_t __u8 ; +typedef uint16_t __u16 ; +typedef uint32_t __u32 ; +#endif + +#include "thinkpad_common.h" +/*#include "thinkpad.h" */ +#include "smapi.h" +#include "smapidev.h" + +/****** defines ******/ + +#define SZ_SMAPIDEV_VERSION "2.0" + +#define SZ_SMAPIDEV_NAME "smapidev" + +/* + * The structures may need to be extended if more + * functionality is added to the SMAPI by IBM. + * + * To cover this, future releases can check the size + * defined in sizeStruct, and reduce the amount of + * information put into the structure accordingly. + */ + +#define SIZE_BIOSINFO_V1 ((size_t)24) +#define SIZE_CPUINFO_V1 ((size_t)16) +#define SIZE_DISPLAYINFO_V1 ((size_t) 8) +#define SIZE_DOCKINGINFO_V1 ((size_t)12) +#define SIZE_ULTRABAYINFO_V1 ((size_t) 8) +#define SIZE_SLAVEINFO_V1 ((size_t)12) +#define SIZE_SENSORINFO_V1 ((size_t) 8) +#define SIZE_SCREENREFRESHINFO_V1 ((size_t)12) +#define SIZE_DISPLAYCAP_V1 ((size_t)12) + + +/****** variables ******/ + +char szSmapidevName[] = SZ_SMAPIDEV_NAME; + + +/****** utility functions ******/ + +/* + * This function returns the binary value of a two-digit bcd number + * If the bcd8 value is 0xFF, as it may be if a location has never been + * initialized in the ThinkPad CMOS RAM, then 0xFF is returned as the + * binary equivalent. + */ +byte byte_of_bcd8( bcd8_t bcd8The ) +{ + byte bTens, bUnits; + + /* catch uninitialized values: simply return them */ + if ( bcd8The == 0xFF ) return 0xFF; + + bUnits = (byte)bcd8The & 0xF; + bTens = (byte)(bcd8The & 0xF0) >> 4; + + if ( bUnits > 9 || bTens > 9 ) { + printf( "%s: Warning: value 0x%x which is supposed to be in BCD format is not; not converting.\n", szSmapidevName, bcd8The ); + return (byte)bcd8The; + } + + return bUnits + (bTens * 10); +} + + +bcd8_t bcd8_of_byte( byte bThe ) +{ + byte bTens, bUnits; + + if ( bThe > 99 ) { + printf( "%s: the value %d being converted to BCD format will be limited to 99.\n", szSmapidevName, bThe ); + bThe = 99; + } + + bTens = bThe / (byte)10; + bUnits = bThe - (bTens * (byte)10); + + return (bTens << 4) | bUnits; +} + +/* + * This function returns the SMAPI BIOS error code if there is one, + * otherwise the ioctl errno as a negative number + */ +int ioctl_smapi( int intFiledesc, smapi_ioparm_t *pioparmThe ) +{ + int intRtn; + + intRtn = ioctl( intFiledesc, IOCTL_SMAPI_REQUEST, pioparmThe ); + if ( intRtn && errno == ETHINKPAD_SUBDRIVER ) return pioparmThe->out.bRc; + if ( intRtn ) return -errno; + return 0; +} + + +/****** functions ******/ + +int smapidev_GetInfo( smapidev_info_t *pinfoThe ) +{ + + strncpy( pinfoThe->szVersion, SZ_SMAPIDEV_VERSION, LEN_VERSION_MAX ); + + /*** Make sure that the returned string is terminated ***/ + pinfoThe->szVersion[LEN_VERSION_MAX] = '\0'; + + return 0; +} + + +/*** smapi-module-access functions ***/ + + +/* + * The Technical Reference fails to mention that the returned + * BIOS revision values are in BCD format + */ +int smapidev_GetBiosInfo( + int intFiledesc, + smapidev_biosinfo_t *pbiosinfoThe +) { + bcd8_t bcd8SysHigh, bcd8SysLow; + bcd8_t bcd8SysMgmtHigh, bcd8SysMgmtLow; + bcd8_t bcd8SMAPIIfaceHigh, bcd8SMAPIIfaceLow; + bcd8_t bcd8VideoHigh, bcd8VideoLow; + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pbiosinfoThe->sizeStruct != SIZE_BIOSINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetBiosInfo\n" , pbiosinfoThe->sizeStruct, SIZE_BIOSINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pbiosinfoThe->wSysId = ioparmThe.out.wParm1; + pbiosinfoThe->wCountryCode = ioparmThe.out.wParm2; + + bcd8SysHigh = (bcd8_t)( ioparmThe.out.wParm3 >> 8 ); + bcd8SysLow = (bcd8_t)( ioparmThe.out.wParm3 & 0xFF ); + pbiosinfoThe->wSysBiosRevMajor = (word) byte_of_bcd8( bcd8SysHigh ); + pbiosinfoThe->wSysBiosRevMinor = (word) byte_of_bcd8( bcd8SysLow ); + + bcd8SysMgmtHigh = (bcd8_t)( (ioparmThe.out.dwParm4 >> 8) & 0xFF ); + bcd8SysMgmtLow = (bcd8_t)( ioparmThe.out.dwParm4 & 0xFF ); + pbiosinfoThe->wSysMgmtBiosRevMajor = (word) byte_of_bcd8( bcd8SysMgmtHigh ); + pbiosinfoThe->wSysMgmtBiosRevMinor = (word) byte_of_bcd8( bcd8SysMgmtLow ); + + bcd8SMAPIIfaceHigh = (bcd8_t)( (ioparmThe.out.dwParm5 >> 8) & 0xFF ); + bcd8SMAPIIfaceLow = (bcd8_t)( ioparmThe.out.dwParm5 & 0xFF ); + pbiosinfoThe->wSmapiBiosIfaceRevMajor = (word) byte_of_bcd8( bcd8SMAPIIfaceHigh ); + pbiosinfoThe->wSmapiBiosIfaceRevMinor = (word) byte_of_bcd8( bcd8SMAPIIfaceLow ); + + /*** Video BIOS info ***/ + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 8; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + bcd8VideoHigh = (bcd8_t)( (ioparmThe.out.wParm1 >> 8) ); + bcd8VideoLow = (bcd8_t)( ioparmThe.out.wParm1 & 0xFF ); + + pbiosinfoThe->wVideoBiosRevMajor = (word) byte_of_bcd8( bcd8VideoHigh ); + pbiosinfoThe->wVideoBiosRevMinor = (word) byte_of_bcd8( bcd8VideoLow ); + + return 0; +} + + +int smapidev_GetCpuInfo( + int intFiledesc, + smapidev_cpuinfo_t *pcpuinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pcpuinfoThe->sizeStruct != SIZE_CPUINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetCpuInfo\n" , pcpuinfoThe->sizeStruct, SIZE_CPUINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 1; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pcpuinfoThe->wManufacturer = (word)( 0xFF & ioparmThe.out.wParm1 ); + pcpuinfoThe->wType = (word)( 0xFF & (ioparmThe.out.wParm2 >> 8) ); + pcpuinfoThe->wStepping = (word)( 0xFF & ioparmThe.out.wParm2 ); + + pcpuinfoThe->wClock = (word)( 0xFF & (ioparmThe.out.wParm3 >> 8) ); + + if ( pcpuinfoThe->wClock == 0xfe ) + pcpuinfoThe->wClock = (word) ioparmThe.out.dwParm4; + + pcpuinfoThe->wInternalClock = (word)( 0xFF & ioparmThe.out.wParm3 ); + if ( pcpuinfoThe->wInternalClock == 0xfe ) + pcpuinfoThe->wInternalClock = (word) ioparmThe.out.dwParm5; + + return 0; +} + + +int smapidev_GetDisplayInfo( + int intFiledesc, + smapidev_displayinfo_t *pdisplayinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdisplayinfoThe->sizeStruct != SIZE_DISPLAYINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDisplayInfo\n" , pdisplayinfoThe->sizeStruct, SIZE_DISPLAYINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 2; + ioparmThe.in.wParm1 = (word) 0x300; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdisplayinfoThe->bPanelType = (byte)(ioparmThe.out.wParm1 >> 8); + pdisplayinfoThe->bPanelDim = (byte)(ioparmThe.out.wParm1 & 0xFF); + pdisplayinfoThe->bCrtType = (byte)(ioparmThe.out.wParm2 >> 8); + pdisplayinfoThe->bCrtFeatures = (byte)(ioparmThe.out.wParm2 & 0xFF); + + return 0; +} + + +int smapidev_GetDockingInfo( + int intFiledesc, + smapidev_dockinginfo_t *pdockinginfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdockinginfoThe->sizeStruct != SIZE_DOCKINGINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDockingInfo\n" , pdockinginfoThe->sizeStruct, SIZE_DOCKINGINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 3; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdockinginfoThe->wID = ioparmThe.out.wParm1; + pdockinginfoThe->fDocked = (flag_t)( ioparmThe.out.bSubRc & 1); + pdockinginfoThe->fKeyUnlocked = (flag_t)((ioparmThe.out.bSubRc >> 6) & 1); + pdockinginfoThe->fBusConnected = (flag_t)((ioparmThe.out.bSubRc >> 7) & 1); + + return 0; +} + + +int smapidev_GetUltrabayInfo( + int intFiledesc, + smapidev_ultrabayinfo_t *pultrabayinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pultrabayinfoThe->sizeStruct != SIZE_ULTRABAYINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetUltrabayInfo\n" , pultrabayinfoThe->sizeStruct, SIZE_ULTRABAYINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 4; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pultrabayinfoThe->bType = (byte)(ioparmThe.out.wParm2 >> 8); + pultrabayinfoThe->bID = (byte)(ioparmThe.out.wParm2 & 0xFF); + + return 0; +} + + +/* + * The ThinkPad 560Z Technical Reference describes function 0:6 as + * "Get Power Management Module Information" while the ThinkPad 600 + * describes it as "Get Slave Micro Control Unit Information" + */ +int smapidev_GetSlaveControllerInfo( + int intFiledesc, + smapidev_slaveinfo_t *pslaveinfoThe +) { + smapi_ioparm_t ioparmThe; + bcd8_t bcd8High = 0, bcd8Low = 0; + flag_t fInvalidID; + int intRtn; + + /* Check structure size */ + if( pslaveinfoThe->sizeStruct != SIZE_SLAVEINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetSlaveControllerInfo\n" , pslaveinfoThe->sizeStruct, SIZE_SLAVEINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 6; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + if ( ioparmThe.out.wParm2 == 0xFFFF ) { + fInvalidID = 1; + } else { + fInvalidID = 0; + bcd8High = (bcd8_t)( ioparmThe.out.wParm2 >> 8 ); + bcd8Low = (bcd8_t)( ioparmThe.out.wParm2 & 0xFF ); + } + + pslaveinfoThe->fAscii = (ioparmThe.out.bSubRc == 0); + if ( fInvalidID ) { + pslaveinfoThe->wIDMajor = 0xFFFF; + pslaveinfoThe->wIDMinor = 0xFFFF; + } else { + pslaveinfoThe->wIDMajor = byte_of_bcd8( bcd8High ); + pslaveinfoThe->wIDMinor = byte_of_bcd8( bcd8Low ); + } + pslaveinfoThe->szID[0] = (char)(0xFF&(ioparmThe.out.wParm2>>8)); + pslaveinfoThe->szID[1] = (char)(0xFF&ioparmThe.out.wParm2); + pslaveinfoThe->szID[2] = '\0'; /* Add zero termination */ + + return 0; +} + + +int smapidev_GetSensorInfo( + int intFiledesc, + smapidev_sensorinfo_t *psensorinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( psensorinfoThe->sizeStruct != SIZE_SENSORINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetSensorInfo\n" , psensorinfoThe->sizeStruct, SIZE_SENSORINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 7; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + psensorinfoThe->fLidClosed = (ioparmThe.out.wParm2 >> 8) & 1; + psensorinfoThe->fKeyboardOpen = (ioparmThe.out.wParm2 >> 9) & 1; + psensorinfoThe->fACAdapterAttached = (ioparmThe.out.wParm2 >> 10) & 1; + + return 0; +} + +int smapidev_GetScreenRefreshInfo( + int intFiledesc, + word wMode, + smapidev_screenrefreshinfo_t *pscreenrefreshinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pscreenrefreshinfoThe->sizeStruct != SIZE_SCREENREFRESHINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetScreenRefreshInfo\n" , pscreenrefreshinfoThe->sizeStruct, SIZE_SCREENREFRESHINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 9; + ioparmThe.in.wParm1 = wMode; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pscreenrefreshinfoThe->f43i = (ioparmThe.out.wParm2 >> 3) & 1; + pscreenrefreshinfoThe->f48i = (ioparmThe.out.wParm2 >> 7) & 1; + pscreenrefreshinfoThe->f56 = (ioparmThe.out.wParm2 >> 4) & 1; + pscreenrefreshinfoThe->f60 = ioparmThe.out.wParm2 & 1; + pscreenrefreshinfoThe->f70 = (ioparmThe.out.wParm2 >> 5) & 1; + pscreenrefreshinfoThe->f72 = (ioparmThe.out.wParm2 >> 1) & 1; + pscreenrefreshinfoThe->f75 = (ioparmThe.out.wParm2 >> 2) & 1; + pscreenrefreshinfoThe->f85 = (ioparmThe.out.wParm2 >> 6) & 1; + + return 0; +} + + +int smapidev_GetDisplayCapability( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_displaycap_t *pdisplaycapThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdisplaycapThe->sizeStruct != SIZE_DISPLAYCAP_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDisplayCapability\n" , pdisplaycapThe->sizeStruct, SIZE_DISPLAYCAP_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x10; + ioparmThe.in.bSubFunc = (byte) 0; + switch ( stateplace ) { + case SMAPIDEV_STATEPLACE_CMOS: ioparmThe.in.wParm1 = (word) 1; break; + case SMAPIDEV_STATEPLACE_CURR: ioparmThe.in.wParm1 = (word) 0; break; + case SMAPIDEV_STATEPLACE_CMOS_AND_CURR: + default: return ERR_SMAPIDEV_PARM_INVALID; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdisplaycapThe->fSupported = (flag_t)(ioparmThe.out.wParm2 & 1); + switch ( ioparmThe.out.wParm2 & 0xFF ) { + case 0: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_NONE; + break; + case 1: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_NONSIMULTANEOUS; + break; + default: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_OTHER; + return ERR_SMAPIDEV_SMAPI_RESULT_NOT_UNDERSTOOD; + } + + return 0; +} + + +int smapidev_GetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmodeThe, + smapidev_ablestate_t *pablestateThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x10; + ioparmThe.in.bSubFunc = (byte) 0; + switch ( stateplace ) { + case SMAPIDEV_STATEPLACE_CMOS: ioparmThe.in.wParm1 = (word) 1; break; + case SMAPIDEV_STATEPLACE_CURR: ioparmThe.in.wParm1 = (word) 0; break; + case SMAPIDEV_STATEPLACE_CMOS_AND_CURR: + default: return ERR_SMAPIDEV_PARM_INVALID; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + switch( dispmodeThe ) + { + case SMAPIDEV_DISPMODE_INTERNAL : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x100 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_CRT : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x200 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_TV : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x400 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x4000 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_DUAL : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x8000 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_SELECT_TV : + *pablestateThe = ( ioparmThe.out.dwParm4 & 1 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + default: + return ERR_SMAPIDEV_PARM_INVALID; + } + + return 0; +} + + +int smapidev_SetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmodeThe, + smapidev_ablestate_t ablestateThe +) { + smapi_ioparm_t ioparmGet; + smapi_ioparm_t ioparmSet; + int intRtn; + + /* We can only update CMOS and current state together */ + if ( stateplace != SMAPIDEV_STATEPLACE_CMOS_AND_CURR ) + return ERR_SMAPIDEV_PARM_INVALID; + + /* No SMAPIDEV_STATE_AUTO or other invalid values are allowed here */ + if( ablestateThe != SMAPIDEV_ABLESTATE_DISABLED && ablestateThe != SMAPIDEV_ABLESTATE_ENABLED ) + { + return ERR_SMAPIDEV_PARM_INVALID; + } + + /* Get the current CMOS state */ + memset( &ioparmGet, 0, sizeof( ioparmGet ) ); + ioparmGet.in.bFunc = (byte) 0x10; + ioparmGet.in.bSubFunc = (byte) 0; + ioparmGet.in.wParm1 = (word) 1; + + intRtn = ioctl_smapi( intFiledesc, &ioparmGet ); + if ( intRtn ) return intRtn; + + memset( &ioparmSet, 0, sizeof( ioparmSet ) ); + ioparmSet.in.bFunc = (byte) 0x10; + ioparmSet.in.bSubFunc = (byte) 1; + ioparmSet.in.wParm1 = ioparmGet.out.wParm2 & 0xC700; + ioparmSet.in.dwParm4 = ioparmGet.out.dwParm4 & 0x0001; + + switch( dispmodeThe ) + { + + case SMAPIDEV_DISPMODE_INTERNAL : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x100; + else + ioparmSet.in.wParm1 &= ~0x100; + break; + + case SMAPIDEV_DISPMODE_CRT : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x200; + else + ioparmSet.in.wParm1 &= ~0x200; + break; + + case SMAPIDEV_DISPMODE_TV : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x400; + else + ioparmSet.in.wParm1 &= ~0x400; + break; + + case SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x4000; + else + ioparmSet.in.wParm1 &= ~0x4000; + break; + + case SMAPIDEV_DISPMODE_DUAL : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x8000; + else + ioparmSet.in.wParm1 &= ~0x8000; + break; + + case SMAPIDEV_DISPMODE_SELECT_TV : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.dwParm4 |= 0x1; + else + ioparmSet.in.dwParm4 &= ~0x1; + break; + + default: + return ERR_SMAPIDEV_PARM_INVALID; + } + + return ioctl_smapi( intFiledesc, &ioparmSet ); +} + + +int smapidev_GetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrcThe, + smapidev_powermode_t *ppowermodeThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + byte bModeAC, bModeBat, bModeSelected; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + bModeAC = (byte)(ioparmThe.out.wParm2 & 0xFF); + bModeBat = (byte)(ioparmThe.out.wParm2 >> 8); + bModeSelected = (powersrcThe == SMAPIDEV_POWERSRC_AC) ? bModeAC : bModeBat; + + switch ( bModeSelected ) { + case 0: *ppowermodeThe = SMAPIDEV_POWERMODE_HIGH; break; + case 1: *ppowermodeThe = SMAPIDEV_POWERMODE_AUTO; break; + case 2: *ppowermodeThe = SMAPIDEV_POWERMODE_MANUAL; break; + default: + case 3: *ppowermodeThe = SMAPIDEV_POWERMODE_UNRECOGNIZED; break; + } + + return 0; +} + + + +int smapidev_SetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrcThe, + smapidev_powermode_t powermodeThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + byte bMode; + + bMode = + (powermodeThe == SMAPIDEV_POWERMODE_HIGH) ? 0 : + (powermodeThe == SMAPIDEV_POWERMODE_AUTO) ? 1 : + 2 + ; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 1; + ioparmThe.in.wParm1 = ioparmThe.out.wParm2; + if ( powersrcThe == SMAPIDEV_POWERSRC_AC ) { + ioparmThe.in.wParm1 &= 0xff00; + ioparmThe.in.wParm1 |= bMode; + } else { /* powersrcThe == SMAPIDEV_POWERSRC_BATTERY */ + ioparmThe.in.wParm1 &= 0x00ff; + ioparmThe.in.wParm1 |= ((word)bMode) << 8; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + return 0; +} +#else +int smapi_dummy(){} +#endif diff --git a/klaptopdaemon/smapidev.h b/klaptopdaemon/smapidev.h new file mode 100644 index 0000000..22deedb --- /dev/null +++ b/klaptopdaemon/smapidev.h @@ -0,0 +1,273 @@ + +/********************************************************************* + * + * Filename: smapidev.h + * Description: Header for the SMAPI device driver access library + * Author: Bill Mair, Thomas Hood + * Created: 13 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 Bill Mair, All rights reserved + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPIDEV_H__ +#define __SMAPIDEV_H__ + +/****** defines ******/ + +/*** smapidev function error codes ***/ +/* + * These codes must not fall in the range 0x0-0xFF which is + * reserved for SMAPI BIOS error codes + */ +#define ERR_SMAPIDEV_MIN ((int)0x1000) +#define ERR_SMAPIDEV_PARM_INVALID ((int)0x1050) +#define ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID ((int)0x1051) +#define ERR_SMAPIDEV_SMAPI_RESULT_NOT_UNDERSTOOD ((int)0x1090) +#define ERR_SMAPIDEV_MAX ((int)0x10FF) + +/****** typedefs ******/ + +/*** enum ***/ + +typedef enum _smapidev_stateplace { + SMAPIDEV_STATEPLACE_CURR=0, + SMAPIDEV_STATEPLACE_CMOS, + SMAPIDEV_STATEPLACE_CMOS_AND_CURR +} smapidev_stateplace_t; + +typedef enum _smapidev_ablestate { + SMAPIDEV_ABLESTATE_DISABLED=0, + SMAPIDEV_ABLESTATE_ENABLED, + SMAPIDEV_ABLESTATE_AUTO +} smapidev_ablestate_t; + +typedef enum _smapidev_displaycaptv { + SMAPIDEV_DISPLAYCAPTV_NONE=0, + SMAPIDEV_DISPLAYCAPTV_NONSIMULTANEOUS, + SMAPIDEV_DISPLAYCAPTV_OTHER +} smapidev_displaycaptv_t; + +/* + * The following are the display modes that can be enabled or disabled + */ +typedef enum _smapidev_dispmode { + SMAPIDEV_DISPMODE_INTERNAL=0, + SMAPIDEV_DISPMODE_CRT, + SMAPIDEV_DISPMODE_TV, + SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE, + SMAPIDEV_DISPMODE_DUAL, + SMAPIDEV_DISPMODE_SELECT_TV +} smapidev_dispmode_t; + +typedef enum _smapidev_fnkeymode { + SMAPIDEV_FNKEY_NORMAL=0, + SMAPIDEV_FNKEY_STICKY, + SMAPIDEV_FNKEY_LOCKED +} smapidev_fnkeymode_t; + +typedef enum _smapidev_ternality { + SMAPIDEV_TERNALITY_IN=0, + SMAPIDEV_TERNALITY_EX +} smapidev_ternality_t; + +typedef enum _smapidev_powersrc { + SMAPIDEV_POWERSRC_AC=0, + SMAPIDEV_POWERSRC_BATTERY +} smapidev_powersrc_t; + +typedef enum _smapidev_powermode { + SMAPIDEV_POWERMODE_HIGH=0, + SMAPIDEV_POWERMODE_AUTO, + SMAPIDEV_POWERMODE_MANUAL, + SMAPIDEV_POWERMODE_UNRECOGNIZED +} smapidev_powermode_t; + + +/*** struct ***/ + +typedef struct _smapidev_info +{ + char szVersion[LEN_VERSION_MAX+1]; +} smapidev_info_t; + +typedef struct _smapidev_biosinfo +{ + size_t sizeStruct; + word wSysId; + word wCountryCode; + word wSysBiosRevMajor; + word wSysBiosRevMinor; + word wSysMgmtBiosRevMajor; + word wSysMgmtBiosRevMinor; + word wSmapiBiosIfaceRevMajor; + word wSmapiBiosIfaceRevMinor; + word wVideoBiosRevMajor; + word wVideoBiosRevMinor; +} smapidev_biosinfo_t; + +typedef struct _smapidev_cpuinfo +{ + size_t sizeStruct; + word wManufacturer; + word wType; + word wStepping; + word wClock; + word wInternalClock; +} smapidev_cpuinfo_t; + +typedef struct _smapidev_displayinfo +{ + size_t sizeStruct; + byte bPanelType; + byte bPanelDim; + byte bCrtType; + byte bCrtFeatures; +} smapidev_displayinfo_t; + +typedef struct _smapidev_dockinginfo +{ + size_t sizeStruct; + word wID; + flag_t fDocked; + flag_t fKeyUnlocked; + flag_t fBusConnected; +} smapidev_dockinginfo_t; + +typedef struct _smapidev_ultrabayinfo +{ + size_t sizeStruct; + byte bType; + byte bID; +} smapidev_ultrabayinfo_t; + +typedef struct _smapidev_slaveinfo +{ + size_t sizeStruct; + flag_t fAscii; + char szID[3]; + word wIDMajor; + word wIDMinor; +} smapidev_slaveinfo_t; + +typedef struct _smapidev_sensorinfo +{ + size_t sizeStruct; + flag_t fLidClosed; + flag_t fKeyboardOpen; + flag_t fACAdapterAttached; +} smapidev_sensorinfo_t; + +typedef struct _smapidev_screenrefreshinfo +{ + size_t sizeStruct; + flag_t f43i; + flag_t f48i; + flag_t f56; + flag_t f60; + flag_t f70; + flag_t f72; + flag_t f75; + flag_t f85; +} smapidev_screenrefreshinfo_t; + +typedef struct _smapidev_displaycap { + size_t sizeStruct; + flag_t fSupported; + smapidev_displaycaptv_t tv; +} smapidev_displaycap_t; + + +/****** function declarations ******/ + +bcd8_t bcd8_of_byte( byte bThe ); +byte byte_of_bcd8( bcd8_t bcd8The ); +int ioctl_smapi( int intFiledesc, smapi_ioparm_t *pioparmThe ); + +/*** Get/Set####Info ***/ + +int smapidev_GetInfo( smapidev_info_t *pinfoThe ); +int smapidev_GetBiosInfo( + int intFiledesc, + smapidev_biosinfo_t *pbiosinfoThe +); +int smapidev_GetCpuInfo( + int intFiledesc, + smapidev_cpuinfo_t *pcpuinfoThe +); +int smapidev_GetDisplayInfo( + int intFiledesc, + smapidev_displayinfo_t *pdisplayinfoThe +); +int smapidev_GetDockingInfo( + int intFiledesc, + smapidev_dockinginfo_t *pdockinginfoThe +); +int smapidev_GetUltrabayInfo( + int intFiledesc, + smapidev_ultrabayinfo_t *pultrabayinfoThe +); +int smapidev_GetSlaveControllerInfo( + int intFiledesc, + smapidev_slaveinfo_t *pslaveinfoThe +); +int smapidev_GetSensorInfo( + int intFiledesc, + smapidev_sensorinfo_t *psensorinfoThe +); +int smapidev_GetScreenRefreshInfo( + int intFiledesc, + word wMode, + smapidev_screenrefreshinfo_t *pscreenrefreshinfoThe +); + +/*** Get/Set####State ***/ + +int smapidev_GetDisplayCapability( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_displaycap_t *pdisplaycap +); +int smapidev_GetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmode, + smapidev_ablestate_t *pablestate +); +int smapidev_SetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmode, + smapidev_ablestate_t ablestate +); + +/*** PM ***/ + +int smapidev_GetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrc, + smapidev_powermode_t *ppowermode +); +int smapidev_SetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrc, + smapidev_powermode_t powermode +); + +#endif diff --git a/klaptopdaemon/sony.cpp b/klaptopdaemon/sony.cpp new file mode 100644 index 0000000..8183f21 --- /dev/null +++ b/klaptopdaemon/sony.cpp @@ -0,0 +1,200 @@ +/* + * sony.cpp + * + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "sony.h" +#include "version.h" +#include "portable.h" + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +// other KDE headers: +#include <klocale.h> +#include <kconfig.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <krichtextlabel.h> + +// other Qt headers: +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qgrid.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtooltip.h> + +extern void wake_laptop_daemon(); + +SonyConfig::SonyConfig(QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + top_layout->addWidget(new KRichTextLabel(i18n("This panel allows you to control some of the features of the\n" + "'sonypi' device for your laptop - you should not enable the options below if you\nalso " + "use the 'sonypid' program in your system").replace("\n", " "), this)); + + enableScrollBar = new QCheckBox( i18n("Enable &scroll bar"), this ); + QToolTip::add( enableScrollBar, i18n( "When checked this box enables the scrollbar so that it works under KDE" ) ); + top_layout->addWidget( enableScrollBar ); + connect( enableScrollBar, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableMiddleEmulation = new QCheckBox( i18n("&Emulate middle mouse button with scroll bar press"), this ); + QToolTip::add( enableMiddleEmulation, i18n( "When checked this box enables pressing the scroll bar to act in the same way as pressing the middle button on a 3 button mouse" ) ); + top_layout->addWidget( enableMiddleEmulation ); + connect( enableMiddleEmulation, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + if (::access("/dev/sonypi", R_OK) != 0) { + enableMiddleEmulation->setEnabled(0); + enableScrollBar->setEnabled(0); + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + top_layout->addWidget(new KRichTextLabel(i18n("The /dev/sonypi is not accessable, if you wish to use the above features its\n" + "protections need to be changed. Clicking on the button below will change them\n").replace("\n", " "), this)); + QHBoxLayout *ll = new QHBoxLayout(); + QPushButton *setupButton = new QPushButton(i18n("Setup /dev/sonypi"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the sony specific features" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + top_layout->addLayout(ll); + } + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +void SonyConfig::setupHelper() +{ + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the protections of /dev/sonypi to be changed."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chmod +r /dev/sonypi"; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The /dev/sonypi protections cannot be changed because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + bool enable = ::access("/dev/sonypi", R_OK) == 0; + enableMiddleEmulation->setEnabled(enable); + enableScrollBar->setEnabled(enable); + wake_laptop_daemon(); +} + +SonyConfig::~SonyConfig() +{ + delete config; +} + +void SonyConfig::save() +{ + enablescrollbar = enableScrollBar->isChecked(); + middleemulation = enableMiddleEmulation->isChecked(); + + config->setGroup("SonyDefault"); + + config->writeEntry("EnableScrollBar", enablescrollbar); + config->writeEntry("EnableMiddleEmulation", middleemulation); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void SonyConfig::load() +{ + load( false ); +} + +void SonyConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("SonyDefault"); + + enablescrollbar = config->readBoolEntry("EnableScrollBar", false); + enableScrollBar->setChecked(enablescrollbar); + middleemulation = config->readBoolEntry("EnableMiddleEmulation", false); + enableMiddleEmulation->setChecked(middleemulation); + + emit changed( useDefaults ); +} + +void SonyConfig::defaults() +{ + load( true ); +} + + +void SonyConfig::configChanged() +{ + emit changed(true); +} + + +QString SonyConfig::quickHelp() const +{ + return i18n("<h1>Sony Laptop Hardware Setup</h1>This module allows you to configure " + "some Sony laptop hardware for your system"); +} + + +void SonyConfig::slotStartMonitor() +{ + wake_laptop_daemon(); +} + + +#include "sony.moc" + + diff --git a/klaptopdaemon/sony.h b/klaptopdaemon/sony.h new file mode 100644 index 0000000..ab31065 --- /dev/null +++ b/klaptopdaemon/sony.h @@ -0,0 +1,71 @@ +/* + * sony.h + * + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __SONYCONFIG_H__ +#define __SONYCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class QSlider; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class SonyConfig : public KCModule +{ + Q_OBJECT +public: + SonyConfig( QWidget *parent=0, const char* name=0); + ~SonyConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void slotStartMonitor(); + void setupHelper(); + +private: + KConfig *config; + + QCheckBox *enableScrollBar; + bool enablescrollbar; + QCheckBox *enableMiddleEmulation; + bool middleemulation; +}; + +#endif + diff --git a/klaptopdaemon/thinkpad_common.h b/klaptopdaemon/thinkpad_common.h new file mode 100644 index 0000000..c347e06 --- /dev/null +++ b/klaptopdaemon/thinkpad_common.h @@ -0,0 +1,127 @@ + +/********************************************************************* + * + * Filename: thinkpad_common.h + * Description: stuff required by the "thinkpad" drivers and + * by programs accessing them + * Author: Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __THINKPAD_COMMON_H__ +#define __THINKPAD_COMMON_H__ + +#include <config.h> +#include <sys/types.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +/* All module (etc.) names should be no longer than this: */ +#define LEN_NAME_MAX 80 + +/* All version strings should be no longer than this: */ +#define LEN_VERSION_MAX 30 + +/****** macros ******/ + +#ifdef DEBUG_IOPARM +#define DEBUG_PRINT_OUTPARMS( ioparmThe ) { \ + printf( "bRc: 0x%x\n", ioparmThe.out.bRc ); \ + printf( "bSubRc: 0x%x\n", ioparmThe.out.bSubRc ); \ + printf( "wParm1: 0x%x\n", ioparmThe.out.wParm1 ); \ + printf( "wParm2: 0x%x\n", ioparmThe.out.wParm2 ); \ + printf( "wParm3: 0x%x\n", ioparmThe.out.wParm3 ); \ + printf( "dwParm4: 0x%lx\n", (unsigned long) ioparmThe.out.dwParm4 ); \ + printf( "dwParm5: 0x%lx\n", (unsigned long) ioparmThe.out.dwParm5 ); \ +} +#define DEBUG_PRINT_INPARMS( ioparmThe ) { \ + printf( "bFunc: 0x%x\n", ioparmThe.in.bFunc ); \ + printf( "bSubFunc: 0x%x\n", ioparmThe.in.bSubFunc ); \ + printf( "wParm1: 0x%x\n", ioparmThe.in.wParm1 ); \ + printf( "wParm2: 0x%x\n", ioparmThe.in.wParm2 ); \ + printf( "wParm3: 0x%x\n", ioparmThe.in.wParm3 ); \ + printf( "dwParm4: 0x%lx\n", (unsigned long) ioparmThe.in.dwParm4 ); \ + printf( "dwParm5: 0x%lx\n", (unsigned long) ioparmThe.in.dwParm5 ); \ +} +#else +#define DEBUG_PRINT_OUTPARMS( ioparmThe ) +#define DEBUG_PRINT_INPARMS( ioparmThe ) +#endif + + +/****** types ******/ +typedef uint8_t byte; +typedef uint16_t word; +typedef uint32_t dword; +typedef char flag_t; +typedef byte bcd8_t; + +/*** ioctl commands ***/ + +/*#include "thinkpad.h" */ +#include "smapi.h" +/*#include "superio.h" */ +/*#include "rtcmosram.h" */ +/*#include "thinkpadpm.h" */ + +#define MAGIC_THINKPAD_IOCTL ('(') +#define IOCTL_THINKPAD_GETVER _IOR (MAGIC_THINKPAD_IOCTL,0x1,thinkpad_ioparm_t) +#define IOCTL_THINKPAD_ENABLE _IOWR(MAGIC_THINKPAD_IOCTL,0x2,thinkpad_ioparm_t) +#define IOCTL_THINKPAD_DISABLE _IOWR(MAGIC_THINKPAD_IOCTL,0x3,thinkpad_ioparm_t) +#define IOCTL_SMAPI_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x10,smapi_ioparm_t) +#define IOCTL_SUPERIO_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x11,superio_ioparm_t) +#define IOCTL_RTCMOSRAM_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x12,rtcmosram_ioparm_t) +#define IOCTL_THINKPADPM_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x20,thinkpadpm_ioparm_t) + +/****** return values ******/ + +/* 0 as a return value always means OK */ + +/* + * We use the following standard UNIX errno's, defined in <asm/errno.h> + * EFAULT memory error + * EBUSY device is already open + * EINVAL function code not recognized + * ENOTTY ioctl code not recognized + * EACCESS inadequate permission to perform action + * + * We use the following standard errnos under names more descriptive + * of our circumstances. Remember that the ioctl handler in the + * driver returns the negatives of these, but they turn up positive + * in user space in errno after an ioctl() call. Our convention + * for ioctl_blah() wrapper functions is to return the errno as a + * negative number. + */ +#define ETHINKPAD_PROGRAMMING (1024) +#define ETHINKPAD_HW_NOT_FOUND (1025) +#define ETHINKPAD_MODULE_DISABLED (1026) +#define ETHINKPAD_MODULE_NOT_FOUND (1027) +#define ETHINKPAD_SUBDRIVER (1028) + +/* + * Subdriver error codes are returned in the parameter block + * and errno is set to THINKPAD_SUBDRIVER + * + */ + +#endif /* __THINKPAD_COMMON_H__ */ diff --git a/klaptopdaemon/version.h b/klaptopdaemon/version.h new file mode 100644 index 0000000..aa0cdd4 --- /dev/null +++ b/klaptopdaemon/version.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2002 Paul Campbell <[email protected]> + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LAPTOP_VERSION "1.4" diff --git a/klaptopdaemon/wake_laptop.cpp b/klaptopdaemon/wake_laptop.cpp new file mode 100644 index 0000000..6b2a2b9 --- /dev/null +++ b/klaptopdaemon/wake_laptop.cpp @@ -0,0 +1,39 @@ +/* + * wake_laptop.cpp + * Copyright (C) 2003 Paul Campbell <[email protected]> + * + * send restart message to laptop daemon thru kded so that the daemon + * gets started if required + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <kprocess.h> +#include <kconfig.h> +#include <kdatastream.h> +#include <dcopclient.h> +#include <kapplication.h> + +KDE_EXPORT void +wake_laptop_daemon() +{ + DCOPClient *dclient = kapp->dcopClient(); + if (!dclient || (!dclient->isAttached() && !dclient->attach())) + return; + + QByteArray data; + QDataStream arg( data, IO_WriteOnly ); + (void) dclient->send( "kded", "klaptopdaemon", "restart()", data ); +} diff --git a/klaptopdaemon/warning.cpp b/klaptopdaemon/warning.cpp new file mode 100644 index 0000000..29944e0 --- /dev/null +++ b/klaptopdaemon/warning.cpp @@ -0,0 +1,602 @@ +/* + * warning.cpp + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "warning.h" +#include "portable.h" +#include "version.h" + +#include <klocale.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kurlrequester.h> +#include <kapplication.h> +#include <kcombobox.h> + +#include <qlayout.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qhbox.h> +#include <qvbuttongroup.h> +#include <qradiobutton.h> +#include <qtooltip.h> + +extern void wake_laptop_daemon(); + +WarningConfig::WarningConfig (int t, QWidget * parent, const char *name) + : KCModule(parent, name), + checkSuspend(0), + checkStandby(0), + checkHibernate(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + type = t; + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + + my_load(0); + + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain, 0); + + top_layout->addStretch(1); + } else { + QGridLayout *grid = new QGridLayout( this, 11, 2, /* rows x cols */ + KDialog::marginHint(), + KDialog::spacingHint() ); + grid->setColStretch( 1, 1 ); + + int curRow = 0; + // setup the trigger stuff: + if (type) { + checkCriticalTime = new QCheckBox( i18n("Critical &trigger:"), this ); + checkCriticalPercent = new QCheckBox( i18n("Critical &trigger:"), this ); + editCriticalTime = new QSpinBox(1, 60*24, 1, this); + editCriticalTime->setSuffix(i18n("keep short, unit in spinbox", "min")); + QToolTip::add(editCriticalTime, i18n("When this amount of battery life is left the actions below will be triggered")); + editCriticalPercent = new QSpinBox(1, 100, 1, this); + editCriticalPercent->setSuffix(i18n("keep short, unit in spinbox", "%")); + QToolTip::add(editCriticalPercent, i18n("When this amount of battery life is left the actions below will be triggered")); + grid->addWidget(checkCriticalTime, curRow, 0); + grid->addWidget(editCriticalTime, curRow++, Qt::AlignLeft); + grid->addWidget(checkCriticalPercent, curRow, 0); + grid->addWidget(editCriticalPercent, curRow++, Qt::AlignLeft); + + connect(editCriticalTime, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(editCriticalPercent, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(checkCriticalTime, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkCriticalPercent, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkCriticalTime, SIGNAL(toggled(bool)), this, SLOT(checkCriticalTimeChanged(bool))); + connect(checkCriticalPercent, SIGNAL(toggled(bool)), this, SLOT(checkCriticalPercentChanged(bool))); + } else { + checkLowTime = new QCheckBox( i18n("Low &trigger:"), this ); + checkLowPercent = new QCheckBox( i18n("Low &trigger:"), this ); + editLowTime = new QSpinBox(1, 60*24, 1, this); + editLowTime->setSuffix(i18n("keep short, unit in spinbox", "min")); + QToolTip::add(editLowTime, i18n("When this amount of battery life is left the actions below will be triggered")); + editLowPercent = new QSpinBox(1, 100, 1, this); + editLowPercent->setSuffix(i18n("keep short, unit in spinbox", "%")); + QToolTip::add(editLowPercent, i18n("When this amount of battery life is left the actions below will be triggered")); + grid->addWidget(checkLowTime, curRow, 0); + grid->addWidget(editLowTime, curRow++, Qt::AlignLeft); + grid->addWidget(checkLowPercent, curRow, 0); + grid->addWidget(editLowPercent, curRow++, Qt::AlignLeft); + + connect(editLowTime, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(editLowPercent, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(checkLowTime, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkLowPercent, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkLowTime, SIGNAL(toggled(bool)), this, SLOT(checkLowTimeChanged(bool))); + connect(checkLowPercent, SIGNAL(toggled(bool)), this, SLOT(checkLowPercentChanged(bool))); + } + + + // setup the Run Command stuff + checkRunCommand = new QCheckBox(i18n("Run &command:"), this); + grid->addWidget(checkRunCommand, curRow, 0); + + editRunCommand = new KURLRequester( this ); + editRunCommand->setEnabled(false); + connect( checkRunCommand, SIGNAL(toggled(bool)), + editRunCommand, SLOT(setEnabled(bool)) ); + connect( checkRunCommand, SIGNAL(clicked()), + this, SLOT(configChanged()) ); + connect( editRunCommand, SIGNAL(textChanged(const QString&)), + this, SLOT(configChanged()) ); + grid->addWidget(editRunCommand, curRow++, 1); + QToolTip::add( editRunCommand, i18n( "This command will be run when the battery gets low" ) ); + + // setup the Play Sound stuff + checkPlaySound = new QCheckBox(i18n("&Play sound:"), this); + grid->addWidget(checkPlaySound, curRow, 0); + + editPlaySound = new KURLRequester( this ); + editPlaySound->setEnabled(false); + connect( checkPlaySound, SIGNAL(toggled(bool)), + editPlaySound, SLOT(setEnabled(bool)) ); + connect( checkPlaySound, SIGNAL(clicked()), + this, SLOT(configChanged()) ); + connect( editPlaySound, SIGNAL(textChanged(const QString&)), + this, SLOT(configChanged()) ); + grid->addWidget(editPlaySound, curRow++, 1); + QToolTip::add( editPlaySound, i18n( "This sound will play when the battery gets low" ) ); + + // setup the System Sound stuff + checkBeep = new QCheckBox(i18n("System &beep"), this); + grid->addWidget(checkBeep, curRow++, 0); + connect(checkBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + QToolTip::add( checkBeep, i18n( "The system will beep if this is enabled" ) ); + + checkNotify = new QCheckBox(i18n("&Notify"), this); + grid->addWidget(checkNotify, curRow++, 0); + connect(checkNotify, SIGNAL(clicked()), this, SLOT(configChanged())); + + int can_suspend = laptop_portable::has_suspend(); + int can_standby = laptop_portable::has_standby(); + int can_hibernate = laptop_portable::has_hibernation(); + int can_brightness = laptop_portable::has_brightness(); + + if (can_brightness) { + checkBrightness = new QCheckBox(i18n("Panel b&rightness"), this); + checkBrightness->setMinimumSize(checkBrightness->sizeHint()); + QToolTip::add( checkBrightness, i18n( "If enabled the back panel brightness will change" ) ); + grid->addWidget(checkBrightness, curRow, 0); + connect(checkBrightness, SIGNAL(toggled(bool)), this, SLOT(brightness_changed(bool))); + QHBoxLayout *v = new QHBoxLayout(); + v->addWidget(new QLabel("-", this)); + valueBrightness = new QSlider(0, 255, 16, 160, Qt::Horizontal, this); + QToolTip::add( valueBrightness, i18n( "How bright or dim to make the back panel" ) ); + valueBrightness->setMaximumWidth(70); + v->addWidget(valueBrightness); + v->addWidget(new QLabel("+", this)); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + valueBrightness->setEnabled(0); + connect(valueBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + ++curRow; + } else { + checkBrightness = 0; + valueBrightness = 0; + } + QStringList performance_list; + int current_performance; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + if (has_performance) { + performance = new QCheckBox(i18n("System performance"), this); + QToolTip::add( performance, i18n( "If enabled the laptop's power performance profile will change" ) ); + grid->addWidget(performance, curRow, 0); + connect (performance, SIGNAL(toggled(bool)), this, SLOT(performance_changed(bool))); + + QHBoxLayout *v = new QHBoxLayout(); + performance_val = new KComboBox(0, this); + performance_val->insertStringList(performance_list); + performance_val->setEnabled(0); + connect (performance_val, SIGNAL(activated(int)), this, SLOT(configChanged())); + QToolTip::add( performance_val, i18n( "The performance profile to change to" ) ); + v->addWidget(performance_val); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + ++curRow; + } else { + performance = 0; + performance_val = 0; + } + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + if (has_throttle) { + throttle = new QCheckBox(i18n("CPU throttling"), this); + QToolTip::add( throttle, i18n( "If enabled the CPU performance will be throttled" ) ); + grid->addWidget(throttle, curRow, 0); + connect (throttle, SIGNAL(toggled(bool)), this, SLOT(throttle_changed(bool))); + + QHBoxLayout *v = new QHBoxLayout(); + throttle_val = new KComboBox(0, this); + throttle_val->insertStringList(throttle_list); + throttle_val->setEnabled(0); + connect (throttle_val, SIGNAL(activated(int)), this, SLOT(configChanged())); + QToolTip::add( throttle_val, i18n( "How much to throttle the CPU performance by" ) ); + v->addWidget(throttle_val); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + ++curRow; + } else { + throttle = 0; + throttle_val = 0; + } + + + + QVButtonGroup *b = new QVButtonGroup(i18n("System State Change"), this); + QToolTip::add( b, i18n( "You may choose one of the following to occur when the battery gets low" ) ); + b->layout()->setSpacing( KDialog::spacingHint() ); + if (can_standby) { + checkStandby = new QRadioButton(i18n("Standb&y"), b); + QToolTip::add( checkStandby, i18n( "Move the system into the standby state - a temporary lower power state" ) ); + checkStandby->setMinimumSize(checkStandby->sizeHint()); + connect(checkStandby, SIGNAL(clicked()), this, SLOT(configChanged())); + } + if (can_suspend) { + checkSuspend = new QRadioButton(i18n("&Suspend"), b); + QToolTip::add( checkSuspend, i18n( "Move the system into the suspend state - also known as 'save-to-ram'" ) ); + checkSuspend->setMinimumSize(checkSuspend->sizeHint()); + connect(checkSuspend, SIGNAL(clicked()), this, SLOT(configChanged())); + } + if (can_hibernate) { + checkHibernate = new QRadioButton(i18n("H&ibernate"), b); + QToolTip::add( checkHibernate, i18n( "Move the system into the hibernate state - also known as 'save-to-disk'" ) ); + checkHibernate->setMinimumSize(checkHibernate->sizeHint()); + connect(checkHibernate, SIGNAL(clicked()), this, SLOT(configChanged())); + } + // setup the logout option + checkLogout = new QRadioButton(i18n("&Logout"), b); + connect(checkLogout, SIGNAL(clicked()), this, SLOT(configChanged())); + // setup the shutdown option + checkShutdown = new QRadioButton(i18n("System power off"), b); + QToolTip::add( checkShutdown, i18n( "Power the laptop off" ) ); + connect(checkShutdown, SIGNAL(clicked()), this, SLOT(configChanged())); + + checkNone = new QRadioButton(i18n("&None"), b); + connect(checkNone, SIGNAL(clicked()), this, SLOT(configChanged())); + + grid->addMultiCellWidget(b, curRow, curRow, 0, 1, Qt::AlignLeft|Qt::AlignTop); + curRow++; + + + QLabel* explain; + if (type) { + explain = new QLabel(i18n("This panel controls how and when you receive warnings that your battery power is going to run out VERY VERY soon."), this); + } else { + explain = new QLabel(i18n("This panel controls how and when you receive warnings that your battery power is about to run out"), this); + } + explain->setAlignment( Qt::WordBreak ); + grid->addMultiCellWidget(explain, curRow, curRow, 0, 1); + ++curRow; + + if (!can_suspend && !can_standby && !can_hibernate) { + // display help text: + QLabel* note = laptop_portable::how_to_do_suspend_resume(this); + grid->addMultiCellWidget(note, curRow, curRow, 0, 1); + ++curRow; + } + grid->setRowStretch(curRow++, 1); + + grid->addWidget(new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), + curRow, 1, Qt::AlignRight); + + } + my_load(1); +} + +WarningConfig::~WarningConfig() +{ + delete config; +} + +void WarningConfig::brightness_changed(bool v) +{ + valueBrightness->setEnabled(v); + configChanged(); +} + +void WarningConfig::throttle_changed(bool v) +{ + throttle_val->setEnabled(v); + configChanged(); +} + +void WarningConfig::performance_changed(bool v) +{ + performance_val->setEnabled(v); + configChanged(); +} + +void WarningConfig::checkLowTimeChanged(bool state) +{ + checkLowPercent->setChecked(state ? false : true); + editLowPercent->setEnabled(state ? false : true); +} + +void WarningConfig::checkLowPercentChanged(bool state) +{ + checkLowTime->setChecked(state ? false : true); + editLowTime->setEnabled(state ? false : true); +} + +void WarningConfig::checkCriticalTimeChanged(bool state) +{ + checkCriticalPercent->setChecked(state ? false : true); + editCriticalPercent->setEnabled(state ? false : true); +} + +void WarningConfig::checkCriticalPercentChanged(bool state) +{ + checkCriticalTime->setChecked(state ? false: true); + editCriticalTime->setEnabled(state ? false : true); +} + + +void WarningConfig::save() +{ + if (apm) { + runcommand = checkRunCommand->isChecked(); + playsound = checkPlaySound->isChecked(); + logout = checkLogout->isChecked(); + shutdown = checkShutdown->isChecked(); + beep = checkBeep->isChecked(); + notify = checkNotify->isChecked(); + do_suspend = (checkSuspend? checkSuspend->isChecked() : false); + do_standby = (checkStandby? checkStandby->isChecked() : false); + do_hibernate = (checkHibernate? checkHibernate->isChecked() : false); + do_brightness = (checkBrightness? checkBrightness->isChecked() : false); + val_brightness = (valueBrightness? valueBrightness->value() : 255); + do_performance = (performance? performance->isChecked() : false); + val_performance = (performance_val? performance_val->currentText() : ""); + do_throttle = (throttle? throttle->isChecked() : false); + val_throttle = (throttle_val? throttle_val->currentText() : ""); + runcommand_val = editRunCommand->url(); + if (type) { + time_based_action_critical = checkCriticalTime->isChecked(); + critical_val_time = editCriticalTime->value(); + critical_val_percent = editCriticalPercent->value(); + } else { + time_based_action_low = checkLowTime->isChecked(); + low_val_time = editLowTime->value(); + low_val_percent = editLowPercent->value(); + } + + sound_val = editPlaySound->url(); + } + config->setGroup((type?"BatteryCritical":"BatteryLow")); + + if (config->group() == "BatteryLow") { + config->writeEntry("TimeBasedAction", time_based_action_low); + config->writeEntry("LowValTime", low_val_time); + config->writeEntry("LowValPercent", low_val_percent); + } else { + config->writeEntry("TimeBasedAction", time_based_action_critical); + config->writeEntry("CriticalValTime", critical_val_time); + config->writeEntry("CriticalValPercent", critical_val_percent); + } + config->writeEntry("RunCommand", runcommand); + config->writeEntry("PlaySound", playsound); + config->writeEntry("Logout", logout); + config->writeEntry("Shutdown", shutdown); + config->writeEntry("SystemBeep", beep); + config->writeEntry("Notify", notify); + config->writeEntry("Suspend", do_suspend); + config->writeEntry("Standby", do_standby); + config->writeEntry("Hibernate", do_hibernate); + config->writeEntry("Brightness", do_brightness); + config->writeEntry("BrightnessValue", val_brightness); + config->writeEntry("Performance", do_performance); + config->writeEntry("PerformanceValue", val_performance); + config->writeEntry("Throttle", do_throttle); + config->writeEntry("ThrottleValue", val_throttle); + config->writeEntry("RunCommandPath", runcommand_val); + config->writeEntry("PlaySoundPath", sound_val); + config->sync(); + wake_laptop_daemon(); +} + +void WarningConfig::load() +{ + load( false ); +} + +void WarningConfig::load(bool useDefaults) +{ + if (config == NULL) + return; + my_load(0, useDefaults); + my_load(1, useDefaults); +} + +void WarningConfig::my_load(int x, bool useDefaults ) +{ + config->setReadDefaults( useDefaults ); + + // open the config file + if (!x) { + config->setGroup((type?"BatteryCritical":"BatteryLow")); + + if (config->group() == "BatteryLow") { + time_based_action_low = config->readBoolEntry("TimeBasedAction", true); + low_val_time = config->readNumEntry("LowValTime", 15); + low_val_percent = config->readNumEntry("LowValPercent", 7); + } else { + time_based_action_critical = config->readBoolEntry("TimeBasedAction", true); + critical_val_time = config->readNumEntry("CriticalValTime", 5); + critical_val_percent = config->readNumEntry("CriticalValPercent", 3); + } + runcommand = config->readBoolEntry("RunCommand", false); + playsound = config->readBoolEntry("PlaySound", false); + logout = config->readBoolEntry("Logout", false); + shutdown = config->readBoolEntry("Shutdown", false); + beep = config->readBoolEntry("SystemBeep", true); + notify = config->readBoolEntry("Notify", (type && checkSuspend ? false : true)); + do_suspend = config->readBoolEntry("Suspend", (type && checkSuspend ? true :false)); + do_standby = config->readBoolEntry("Standby", false); + do_hibernate = config->readBoolEntry("Hibernate", false); + do_brightness = config->readBoolEntry("Brightness", false); + val_brightness = config->readNumEntry("BrightnessValue", 255); + do_performance = config->readBoolEntry("Performance", false); + val_performance = config->readEntry("PerformanceValue", ""); + do_throttle = config->readBoolEntry("Throttle", false); + val_throttle = config->readEntry("ThrottleValue", ""); + runcommand_val = config->readEntry("RunCommandPath"); + sound_val = config->readEntry("PlaySoundPath"); + have_time = config->readNumEntry("HaveTime", 2); + if (laptop_portable::has_power_management()) + have_time = laptop_portable::has_battery_time(); + + } else + if (apm) { + checkRunCommand->setChecked(runcommand); + checkPlaySound->setChecked(playsound); + checkBeep->setChecked(beep); + if (checkBrightness) + checkBrightness->setChecked(do_brightness); + if (valueBrightness) { + valueBrightness->setValue(val_brightness); + valueBrightness->setEnabled(do_brightness); + } + if (performance) + performance->setChecked(do_performance); + if (performance_val) { + int ind = 0; + for (int i = 0; i < performance_val->count(); i++) + if (performance_val->text(i) == val_performance) { + ind = i; + break; + } + performance_val->setCurrentItem(ind); + performance_val->setEnabled(do_performance); + } + if (throttle) + throttle->setChecked(do_throttle); + if (throttle_val) { + int ind = 0; + for (int i = 0; i < throttle_val->count(); i++) + if (throttle_val->text(i) == val_throttle) { + ind = i; + break; + } + throttle_val->setCurrentItem(ind); + throttle_val->setEnabled(do_throttle); + } + + checkLogout->setChecked(logout); + checkNotify->setChecked(notify); + checkShutdown->setChecked(shutdown); + if (checkHibernate) { + checkHibernate->setChecked(do_hibernate); + } else { + do_hibernate = 0; + } + if (checkStandby) { + checkStandby->setChecked(do_standby); + } else { + do_standby = 0; + } + if (checkSuspend) { + checkSuspend->setChecked(do_suspend); + } else { + do_suspend = 0; + } + checkNone->setChecked(!do_suspend&!do_standby&!do_hibernate&!logout&!shutdown); + editRunCommand->setURL(runcommand_val); + + if(type) { + checkCriticalTime->setChecked(time_based_action_critical ? true : false); + editCriticalTime->setValue(critical_val_time); + checkCriticalPercent->setChecked(time_based_action_critical ? false : true); + editCriticalPercent->setValue(critical_val_percent); + } else { + checkLowTime->setChecked(time_based_action_low ? true : false); + editLowTime->setValue(low_val_time); + checkLowPercent->setChecked(time_based_action_low ? false : true); + editLowPercent->setValue(low_val_percent); + } + + editPlaySound->setURL(sound_val); + } + emit changed(useDefaults); +} + +void WarningConfig::defaults() +{ + load( true ); +} + + +void WarningConfig::configChanged() +{ + emit changed(true); +} + + +#if 0 +void WarningConfig::enableRunCommand(bool enable) +{ + editRunCommand->setEnabled(enable); + buttonBrowseRunCommand->setEnabled(enable); + configChanged(); +} + +void WarningConfig::enablePlaySound(bool enable) +{ + editPlaySound->setEnabled(enable); + buttonBrowsePlaySound->setEnabled(enable); + configChanged(); +} + +void WarningConfig::browseRunCommand() +{ + KURL url = KFileDialog::getOpenURL(QString::null, QString::null, this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) ); + return; + } + + editRunCommand->setText( url.path() ); + configChanged(); +} + +void WarningConfig::browsePlaySound() +{ + KURL url = KFileDialog::getOpenURL(QString::null, QString::null, this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) ); + return; + } + + editPlaySound->setText( url.path() ); + configChanged(); +} +#endif + +QString WarningConfig::quickHelp() const +{ + return i18n("<h1>Low battery Warning</h1>This module allows you to " + "set an alarm in case your battery's charge is about to run out."); +} + +#include "warning.moc" diff --git a/klaptopdaemon/warning.h b/klaptopdaemon/warning.h new file mode 100644 index 0000000..3eb1b04 --- /dev/null +++ b/klaptopdaemon/warning.h @@ -0,0 +1,106 @@ +/* + * warning.h + * + * Copyright (c) 1999 Paul Campbell <[email protected]> + * Copyright (c) 2002 Marc Mutz <[email protected]> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __WARNINGCONFIG_H__ +#define __WARNINGCONFIG_H__ + +#include <kcmodule.h> +#include <qstring.h> + +class QWidget; +class KConfig; +class KURLRequester; +class QCheckBox; +class QRadioButton; +class QSpinBox; +class QSlider; +class KComboBox; + +class WarningConfig : public KCModule +{ + Q_OBJECT +public: + WarningConfig(int x, QWidget *parent=0, const char* name=0); + ~WarningConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + void configChanged(); + void brightness_changed(bool v); + void throttle_changed(bool v); + void performance_changed(bool v); + void checkLowTimeChanged(bool state); + void checkLowPercentChanged(bool state); + void checkCriticalTimeChanged(bool state); + void checkCriticalPercentChanged(bool state); + +private: + void my_load(int x, bool useDefaults=false ); + + KConfig *config; + + KURLRequester* editRunCommand; + KURLRequester* editPlaySound; + QCheckBox* checkLowTime; + QCheckBox* checkLowPercent; + QCheckBox* checkCriticalTime; + QCheckBox* checkCriticalPercent; + QSpinBox* editLowTime; + QSpinBox* editLowPercent; + QSpinBox* editCriticalTime; + QSpinBox* editCriticalPercent; + + QCheckBox *checkRunCommand; + QCheckBox *checkPlaySound; + QCheckBox *checkBeep; + QCheckBox *checkNotify; + QCheckBox *checkBrightness; + QSlider *valueBrightness; + QCheckBox *performance, *throttle; + KComboBox *performance_val, *throttle_val; + QRadioButton *checkNone; + QRadioButton *checkShutdown; + QRadioButton *checkLogout; + QRadioButton *checkSuspend; + QRadioButton *checkStandby; + QRadioButton *checkHibernate; + + bool apm, runcommand, playsound, beep, notify, do_suspend, do_standby, do_hibernate, logout, shutdown, do_brightness; + bool do_performance, do_throttle; + bool time_based_action_low, time_based_action_critical; + QString val_performance, val_throttle; + int val_brightness; + QString runcommand_val, sound_val; + int low_val_time, low_val_percent, critical_val_time, critical_val_percent; + int have_time, type; +}; + +#endif + diff --git a/klaptopdaemon/xautolock.cc b/klaptopdaemon/xautolock.cc new file mode 100644 index 0000000..4f856e1 --- /dev/null +++ b/klaptopdaemon/xautolock.cc @@ -0,0 +1,277 @@ +//---------------------------------------------------------------------------- +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Lubos Lunak <[email protected]> +// +// KDE screensaver engine +// + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "xautolock.h" +#include "xautolock.moc" + +#include <kapplication.h> +#include <kdebug.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <ctime> +#include "xautolock_c.h" + +#ifdef HAVE_DPMS +extern "C" { +#include <X11/Xmd.h> +#ifndef Bool +#define Bool BOOL +#endif +#include <X11/extensions/dpms.h> + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} +#endif + +int xautolock_useXidle = 0; +int xautolock_useMit = 0; +xautolock_corner_t xautolock_corners[ 4 ]; + +static XAutoLock* self = NULL; + +static int catchFalseAlarms(Display *, XErrorEvent *) +{ + return 0; +} + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +XAutoLock::XAutoLock() +{ + self = this; + int dummy = 0; + dummy = dummy; // shut up + xautolock_useXidle = 0; + xautolock_useMit = 0; +#ifdef HAVE_XIDLE + useXidle = XidleQueryExtension( qt_xdisplay(), &dummy, &dummy ); +#endif +#ifdef HAVE_XSCREENSAVER + if( !xautolock_useXidle ) + xautolock_useMit = XScreenSaverQueryExtension( qt_xdisplay(), &dummy, &dummy ); +#endif + if( !xautolock_useXidle && !xautolock_useMit ) + { + kapp->installX11EventFilter( this ); + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(catchFalseAlarms); + XSync(qt_xdisplay(), False ); + xautolock_initDiy( qt_xdisplay()); + XSync(qt_xdisplay(), False ); + XSetErrorHandler(oldHandler); + } + + mTimeout = DEFAULT_TIMEOUT; + mDPMS = true; + resetTrigger(); + + time(&mLastTimeout); + mActive = false; + + mTimerId = startTimer( CHECK_INTERVAL ); + +} + +//--------------------------------------------------------------------------- +// +// Destructor. +// +XAutoLock::~XAutoLock() +{ + self = NULL; +} + +//--------------------------------------------------------------------------- +// +// The time in seconds of continuous inactivity. +// +void XAutoLock::setTimeout(int t) +{ + mTimeout = t; + resetTrigger(); +} + +void XAutoLock::setDPMS(bool s) +{ + mDPMS = s; +} + +//--------------------------------------------------------------------------- +// +// Start watching Activity +// +void XAutoLock::start() +{ + resetTrigger(); + time(&mLastTimeout); + mActive = true; +} + +//--------------------------------------------------------------------------- +// +// Stop watching Activity +// +void XAutoLock::stop() +{ + mActive = false; +} + +//--------------------------------------------------------------------------- +// +// Reset the trigger time. +// +void XAutoLock::resetTrigger() +{ + mTrigger = time(0) + mTimeout; +} + +//--------------------------------------------------------------------------- +// +// Move the trigger time in order to postpone (repeat) emitting of timeout(). +// +void XAutoLock::postpone() +{ + mTrigger = time(0) + 60; // delay by 60sec +} + +//--------------------------------------------------------------------------- +// +// Set the remaining time to 't', if it's shorter than already set. +// +void XAutoLock::setTrigger( time_t t ) +{ + if( t < mTrigger ) + mTrigger = t; +} + +//--------------------------------------------------------------------------- +// +// Process new windows and check the mouse. +// +void XAutoLock::timerEvent(QTimerEvent *ev) +{ + if (ev->timerId() != mTimerId) + { + return; + } + + int (*oldHandler)(Display *, XErrorEvent *) = NULL; + if( !xautolock_useXidle && !xautolock_useMit ) + { // only the diy way needs special X handler + XSync( qt_xdisplay(), False ); + oldHandler = XSetErrorHandler(catchFalseAlarms); + } + + xautolock_processQueue(); + + time_t now = time(0); + if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) || + (mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1)) + { + /* the time has changed in one large jump. This could be because + the date was changed, or the machine was suspended. We'll just + reset the triger. */ + resetTrigger(); + } + + mLastTimeout = now; + + xautolock_queryIdleTime( qt_xdisplay()); + xautolock_queryPointer( qt_xdisplay()); + + if( !xautolock_useXidle && !xautolock_useMit ) + XSetErrorHandler(oldHandler); + + bool activate = false; + + //kdDebug() << now << " " << mTrigger << endl; + if (now >= mTrigger) + { + resetTrigger(); + activate = true; + } + +#ifdef HAVE_DPMS + BOOL on; + CARD16 state; + DPMSInfo( qt_xdisplay(), &state, &on ); + + //kdDebug() << "DPMSInfo " << state << " " << on << endl; + // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time + // that is always smaller than DPMS timeout (X bug I guess). So if DPMS + // saving is active, simply always activate our saving too, otherwise + // this could prevent locking from working. + if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff) + activate = true; + if(!on && mDPMS) { + activate = false; + resetTrigger(); + } +#endif + +#ifdef HAVE_XSCREENSAVER + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + if (XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow (qt_xdisplay()), mitInfo)) { + //kdDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl; + if (mitInfo->state == ScreenSaverDisabled) + activate = false; + } +#endif + + if(mActive && activate) + emit timeout(); +} + +bool XAutoLock::x11Event( XEvent* ev ) +{ + xautolock_processEvent( ev ); +// don't futher process key events that were received only because XAutoLock wants them + if( ev->type == KeyPress && !ev->xkey.send_event + && !xautolock_useXidle && !xautolock_useMit + && !QWidget::find( ev->xkey.window )) + return true; + return false; +} + +bool XAutoLock::ignoreWindow( WId w ) +{ + if( w != qt_xrootwin() && QWidget::find( w )) + return true; + return false; +} + +extern "C" +void xautolock_resetTriggers() +{ + self->resetTrigger(); +} + +extern "C" +void xautolock_setTrigger( time_t t ) +{ + self->setTrigger( t ); +} + +extern "C" +int xautolock_ignoreWindow( Window w ) +{ + return self->ignoreWindow( w ); +} diff --git a/klaptopdaemon/xautolock.h b/klaptopdaemon/xautolock.h new file mode 100644 index 0000000..aa618f2 --- /dev/null +++ b/klaptopdaemon/xautolock.h @@ -0,0 +1,77 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// + +#ifndef __XAUTOLOCK_H__ +#define __XAUTOLOCK_H__ + +#include <qwidget.h> + +#include <X11/Xlib.h> + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +class XAutoLock : public QWidget +{ + Q_OBJECT +public: + XAutoLock(); + ~XAutoLock(); + + //----------------------------------------------------------------------- + // + // The time in seconds of continuous inactivity. + // + void setTimeout(int t); + + void setDPMS(bool s); + + //----------------------------------------------------------------------- + // + // Start watching Activity + // + void start(); + + //----------------------------------------------------------------------- + // + // Stop watching Activity + // + void stop(); + + //----------------------------------------------------------------------- + // + // Should be called only from a slot connected to the timeout() signal. Will + // result in the timeout() signal being emitted again with a delay (i.e. postponed). + // + void postpone(); + + // internal + void resetTrigger(); + // internal + void setTrigger( time_t ); + // internal + bool ignoreWindow( WId ); + +signals: + void timeout(); + +protected: + virtual void timerEvent(QTimerEvent *ev); + virtual bool x11Event( XEvent* ); + +protected: + int mTimerId; + int mTimeout; + time_t mTrigger; + bool mActive; + time_t mLastTimeout; + bool mDPMS; +}; + +#endif diff --git a/klaptopdaemon/xautolock_c.h b/klaptopdaemon/xautolock_c.h new file mode 100644 index 0000000..a53ad93 --- /dev/null +++ b/klaptopdaemon/xautolock_c.h @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It takes care + * of most OS dependencies, and defines the program's default + * settings. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#ifndef __xautolock_c_h +#define __xautolock_c_h + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XSCREENSAVER +#define HasScreenSaver +#include <X11/extensions/scrnsaver.h> +#endif + +/* I'd first need to get my hands on this */ +#undef HAVE_XIDLE +#undef HasXidle + +#define DEFAULT_TIMEOUT 600 + +#define CHECK_INTERVAL 5000 /* ms */ + +#define CREATION_DELAY 30 /* should be > 10 and + < min (45,(MIN_MINUTES*30)) */ +#define TIME_CHANGE_LIMIT 120 /* if the time changes by more + than x secs then we will + assume someone has changed + date or machine has suspended */ + +#define cornerSize 5 + +#define cornerDelay 5 + +#define cornerRedelay 5 + +typedef enum { ca_nothing, ca_dontLock, ca_forceLock } xautolock_corner_t; + +#ifdef __cplusplus +extern "C" +{ +#endif +void xautolock_processEvent( XEvent* ev ); +void xautolock_queryIdleTime( Display* d); +void xautolock_processQueue( void ); +void xautolock_queryPointer (Display* d); +void xautolock_initDiy (Display* d); +void xautolock_resetTriggers( void ); +void xautolock_setTrigger( time_t ); +int xautolock_ignoreWindow( Window ); +extern int xautolock_useXidle; +extern int xautolock_useMit; +extern xautolock_corner_t xautolock_corners[ 4 ]; +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/klaptopdaemon/xautolock_diy.c b/klaptopdaemon/xautolock_diy.c new file mode 100644 index 0000000..b9df2f8 --- /dev/null +++ b/klaptopdaemon/xautolock_diy.c @@ -0,0 +1,289 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the stuff used when the program is not using a screen saver + * extension and thus has to use the good old "do it yourself" + * approach for detecting user activity. + * + * The basic idea is that we initially traverse the window tree, + * selecting SubstructureNotify on all windows and adding each + * window to a temporary list. About +- 30 seconds later, we + * scan this list, now asking for KeyPress events. The delay + * is needed in order to interfere as little as possible with + * the event propagation mechanism. Whenever a new window is + * created by an application, a similar process takes place. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include <X11/Xlib.h> +#include <stdlib.h> +#include <time.h> + +#include "xautolock_c.h" + +static void selectEvents (Window window, Bool substructureOnly); + +/* + * Window queue management. + */ +typedef struct item +{ + Window window; + time_t creationtime; + struct item* next; +} xautolock_anItem, *xautolock_item; + +static struct +{ + Display* display; + struct item* head; + struct item* tail; +} queue; + +static void +addToQueue (Window window) +{ + xautolock_item newItem = malloc(sizeof(xautolock_anItem)); + + newItem->window = window; + newItem->creationtime = time (0); + newItem->next = 0; + + if (!queue.head) queue.head = newItem; + if ( queue.tail) queue.tail->next = newItem; + + queue.tail = newItem; +} + +static void +processQueue (time_t age) +{ + if (queue.head) + { + time_t now = time (0); + xautolock_item current = queue.head; + + while (current && current->creationtime + age < now) + { + selectEvents (current->window, False); + queue.head = current->next; + free (current); + current = queue.head; + } + + if (!queue.head) queue.tail = 0; + } +} + +/* + * Function for selecting all interesting events on a given + * (tree of) window(s). + */ +static void +selectEvents (Window window, Bool substructureOnly) +{ + Window root; /* root window of the window */ + Window parent; /* parent of the window */ + Window* children; /* children of the window */ + unsigned nofChildren = 0; /* number of children */ + unsigned i; /* loop counter */ + XWindowAttributes attribs; /* attributes of the window */ + + if( xautolock_ignoreWindow( window )) + return; + /* + * Start by querying the server about the root and parent windows. + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + if (nofChildren) (void) XFree ((char*) children); + + /* + * Build the appropriate event mask. The basic idea is that we don't + * want to interfere with the normal event propagation mechanism if + * we don't have to. + * + * On the root window, we need to ask for both substructureNotify + * and KeyPress events. On all other windows, we always need + * substructureNotify, but only need Keypress if some other client + * also asked for them, or if they are not being propagated up the + * window tree. + */ +#if 0 + if (substructureOnly) + { + (void) XSelectInput (queue.display, window, SubstructureNotifyMask); + } + else + { + if (parent == None) /* the *real* rootwindow */ + { + attribs.all_event_masks = + attribs.do_not_propagate_mask = KeyPressMask; + } + else if (!XGetWindowAttributes (queue.display, window, &attribs)) +#else + { + if (!XGetWindowAttributes (queue.display, window, &attribs)) +#endif + { + return; + } + +#if 0 + (void) XSelectInput (queue.display, window, + SubstructureNotifyMask + | ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask)); +#else + { + int mask = SubstructureNotifyMask | attribs.your_event_mask; + if( !substructureOnly ) + { + mask |= ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask ); + } + (void) XSelectInput (queue.display, window, mask ); + } +#endif + + } + + /* + * Now ask for the list of children again, since it might have changed + * in between the last time and us selecting SubstructureNotifyMask. + * + * There is a (very small) chance that we might process a subtree twice: + * child windows that have been created after our XSelectinput() has + * been processed but before we get to the XQueryTree() bit will be + * in this situation. This is harmless. It could be avoided by using + * XGrabServer(), but that'd be an impolite thing to do, and since it + * isn't required... + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + /* + * Now do the same thing for all children. + */ + for (i = 0; i < nofChildren; ++i) + { + selectEvents (children[i], substructureOnly); + } + + if (nofChildren) (void) XFree ((char*) children); +} + +#if 0 +/* + * Function for processing any events that have come in since + * last time. It is crucial that this function does not block + * in case nothing interesting happened. + */ +void +processEvents (void) +{ + while (XPending (queue.display)) + { + XEvent event; + + if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event)) + { + if (event.type == CreateNotify) + { + addToQueue (event.xcreatewindow.window); + } + } + else + { + (void) XNextEvent (queue.display, &event); + } + + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event.type == KeyPress + && !event.xany.send_event) + { + resetTriggers (); + } + } + + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#else +void xautolock_processEvent( XEvent* event ) +{ + if (event->type == CreateNotify) + { + addToQueue (event->xcreatewindow.window); + } + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event->type == KeyPress + && !event->xany.send_event) + { + xautolock_resetTriggers (); + } +} + +void xautolock_processQueue() +{ + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#endif + + +/* + * Function for initialising the whole shebang. + */ +void +xautolock_initDiy (Display* d) +{ + int s; + + queue.display = d; + queue.tail = 0; + queue.head = 0; + + for (s = -1; ++s < ScreenCount (d); ) + { + Window root = RootWindowOfScreen (ScreenOfDisplay (d, s)); + addToQueue (root); +#if 0 + selectEvents (root, True); +#endif + } +} diff --git a/klaptopdaemon/xautolock_engine.c b/klaptopdaemon/xautolock_engine.c new file mode 100644 index 0000000..62f968a --- /dev/null +++ b/klaptopdaemon/xautolock_engine.c @@ -0,0 +1,419 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the program's core functions. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include <X11/Xlib.h> +#include <time.h> + +#include "xautolock_c.h" + +/* + * Function for querying the idle time from the server. + * Only used if either the Xidle or the Xscreensaver + * extension is present. + */ +void +xautolock_queryIdleTime (Display* d) +{ + Time idleTime = 0; /* millisecs since last input event */ + +#ifdef HasXidle + if (xautolock_useXidle) + { + XGetIdleTime (d, &idleTime); + } + else +#endif /* HasXIdle */ + { +#ifdef HasScreenSaver + if( xautolock_useMit ) + { + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (d, DefaultRootWindow (d), mitInfo); + idleTime = mitInfo->idle; + } + else +#endif /* HasScreenSaver */ + { + d = d; /* shut up */ + return; /* DIY */ + } + } + + if (idleTime < CHECK_INTERVAL ) + { + xautolock_resetTriggers (); + } +} + +/* + * Function for monitoring pointer movements. This implements the + * `corners' feature and as a side effect also tracks pointer + * related user activity. The latter actually is only needed when + * we're using the DIY mode of operations, but it's much simpler + * to do it unconditionally. + */ +void +xautolock_queryPointer (Display* d) +{ + Window dummyWin; /* as it says */ + int dummyInt; /* as it says */ + unsigned mask; /* modifier mask */ + int rootX; /* as it says */ + int rootY; /* as it says */ + int corner; /* corner index */ + time_t now; /* as it says */ + time_t newTrigger; /* temporary storage */ + int i; /* loop counter */ + static Window root; /* root window the pointer is on */ + static Screen* screen; /* screen the pointer is on */ + static unsigned prevMask = 0; /* as it says */ + static int prevRootX = -1; /* as it says */ + static int prevRootY = -1; /* as it says */ + static Bool firstCall = True; /* as it says */ + + /* + * Have a guess... + */ + if (firstCall) + { + firstCall = False; + root = DefaultRootWindow (d); + screen = ScreenOfDisplay (d, DefaultScreen (d)); + } + + /* + * Find out whether the pointer has moved. Using XQueryPointer for this + * is gross, but it also is the only way never to mess up propagation + * of pointer events. + */ + if (!XQueryPointer (d, root, &root, &dummyWin, &rootX, &rootY, + &dummyInt, &dummyInt, &mask)) + { + /* + * Pointer has moved to another screen, so let's find out which one. + */ + for (i = -1; ++i < ScreenCount (d); ) + { + if (root == RootWindow (d, i)) + { + screen = ScreenOfDisplay (d, i); + break; + } + } + } + + if ( rootX == prevRootX + && rootY == prevRootY + && mask == prevMask) + { + xautolock_corner_t* corners = xautolock_corners; + /* + * If the pointer has not moved since the previous call and + * is inside one of the 4 corners, we act according to the + * contents of the "corners" array. + * + * If rootX and rootY are less than zero, don't lock even if + * ca_forceLock is set in the upper-left corner. Why? 'cause + * on initial server startup, if (and only if) the pointer is + * never moved, XQueryPointer() can return values less than + * zero (only some servers, Openwindows 2.0 and 3.0 in + * particular). + */ + if ( (corner = 0, + rootX <= cornerSize && rootX >= 0 + && rootY <= cornerSize && rootY >= 0) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY <= cornerSize) + || (corner++, + rootX <= cornerSize + && rootY >= HeightOfScreen (screen) - cornerSize - 1) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY >= HeightOfScreen (screen) - cornerSize - 1)) + { + now = time (0); + + switch (corners[corner]) + { + case ca_forceLock: +#if 0 + newTrigger = now + (useRedelay ? cornerRedelay : cornerDelay) - 1; +#else + newTrigger = now + 2 - 1; +#endif + +#if 0 + if (newTrigger < lockTrigger) + { + setLockTrigger (newTrigger - now); + } +#else + xautolock_setTrigger( newTrigger ); +#endif + break; + + case ca_dontLock: + xautolock_resetTriggers (); + +#ifdef __GNUC__ + default: ; /* Makes gcc -Wall shut up. */ +#endif /* __GNUC__ */ + } + } + } + else + { +#if 0 + useRedelay = False; +#endif + prevRootX = rootX; + prevRootY = rootY; + prevMask = mask; + + xautolock_resetTriggers (); + } +} + +#if 0 +/* + * Support for deciding whether to lock or kill. + */ +void +evaluateTriggers (Display* d) +{ + static time_t prevNotification = 0; + time_t now = 0; + + /* + * Obvious things first. + * + * The triggers are being moved all the time while in disabled + * mode in order to make absolutely sure we cannot run into + * trouble by an enable message coming in at an odd moment. + * Otherwise we possibly might lock or kill too soon. + */ + if (disabled) + { + resetTriggers (); + } + + /* + * Next, wait for (or kill, if we were so told) the previous + * locker (if any). Note that this must also be done while in + * disabled mode. Not only to avoid a potential zombie proces + * hanging around until we are re-enabled, but also to prevent + * us from incorrectly setting a kill trigger at the moment + * when we are finally re-enabled. + */ +#ifdef VMS + if (vmsStatus == 0) + { +#else /* VMS */ + if (lockerPid) + { +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + union wait status; /* childs process status */ +#else /* !UTEKV && !SYSV && !SVR4 */ + int status = 0; /* childs process status */ +#endif /* !UTEKV && !SYSV && !SVR4 */ + + if (unlockNow && !disabled) + { + (void) kill (lockerPid, SIGTERM); + } + +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + if (wait3 (&status, WNOHANG, 0)) +#else /* !UTEKV && !SYSV && !SVR4 */ + if (waitpid (-1, &status, WNOHANG)) +#endif /* !UTEKV && !SYSV && !SVR4 */ + { + /* + * If the locker exited normally, we disable any pending kill + * trigger. Otherwise, we assume that it either has crashed or + * was not able to lock the display because of an existing + * locker (which may have been started manually). In both of + * the later cases, disabling the kill trigger would open a + * loop hole. + */ + if ( WIFEXITED (status) + && WEXITSTATUS (status) == EXIT_SUCCESS) + { + disableKillTrigger (); + } + + useRedelay = True; + lockerPid = 0; + } +#endif /* VMS */ + + setLockTrigger (lockTime); + + /* + * No return here! The pointer may be sitting in a corner, while + * parameter settings may be such that we need to start another + * locker without further delay. If you think this cannot happen, + * consider the case in which the locker simply crashed. + */ + } + + unlockNow = False; + + /* + * Note that the above lot needs to be done even when we're in + * disabled mode, since we may have entered said mode with an + * active locker around. + */ + if (disabled) return; + + /* + * Is it time to run the killer command? + */ + now = time (0); + + if (killTrigger && now >= killTrigger) + { + /* + * There is a dirty trick here. On the one hand, we don't want + * to block until the killer returns, but on the other one + * we don't want to have it interfere with the wait() stuff we + * do to keep track of the locker. To obtain both, the killer + * command has already been patched by KillerChecker() so that + * it gets backgrounded by the shell started by system(). + * + * For the time being, VMS users are out of luck: their xautolock + * will indeed block until the killer returns. + */ + (void) system (killer); + setKillTrigger (killTime); + } + + /* + * Now trigger the notifier if required. + */ + if ( notifyLock + && now + notifyMargin >= lockTrigger + && prevNotification < now - notifyMargin - 1) + { + if (notifierSpecified) + { + /* + * Here we use the same dirty trick as for the killer command. + */ + (void) system (notifier); + } + else + { + (void) XBell (d, bellPercent); + (void) XSync (d, 0); + } + + prevNotification = now; + } + + /* + * Finally fire up the locker if time has somehow come. + */ + if ( lockNow + || now >= lockTrigger) + { +#ifdef VMS + if (vmsStatus != 0) +#else /* VMS */ + if (!lockerPid) +#endif /* VMS */ + { + switch (lockerPid = vfork ()) + { + case -1: + lockerPid = 0; + break; + + case 0: + (void) close (ConnectionNumber (d)); +#ifdef VMS + vmsStatus = 0; + lockerPid = lib$spawn ((lockNow ? &nowLockerDescr : &lockerDescr), + 0, 0, &1, 0, 0, &vmsStatus); + + if (!(lockerPid & 1)) exit (lockerPid); + +#ifdef SLOW_VMS + (void) sleep (SLOW_VMS_DELAY); +#endif /* SLOW_VMS */ +#else /* VMS */ + (void) execl ("/bin/sh", "/bin/sh", "-c", + (lockNow ? nowLocker : locker), 0); +#endif /* VMS */ + _exit (EXIT_FAILURE); + + default: + /* + * In general xautolock should keep its fingers off the real + * screensaver because no universally acceptable policy can + * be defined. In no case should it decide to disable or enable + * it all by itself. Setting the screensaver policy is something + * the locker should take care of. After all, xautolock is not + * supposed to know what the "locker" does and doesn't do. + * People might be using xautolock for totally different + * purposes (which, by the way, is why it will accept a + * different set of X resources after being renamed). + * + * Nevertheless, simply resetting the screensaver is a + * convenience action that aids many xlock users, and doesn't + * harm anyone (*). The problem with older versions of xlock + * is that they can be told to replace (= disable) the real + * screensaver, but forget to reset that same screensaver if + * it was already active at the time xlock starts. I guess + * xlock initially wasn't designed to be run without a user + * actually typing the comand ;-). + * + * (*) Well, at least it used not to harm anyone, but with the + * advent of DPMS monitors, it now can mess up the power + * saving setup. Hence we better make it optional. + * + * Also, some xlock versions also unconditionally call + * XResetScreenSaver, yielding the same kind of problems + * with DPMS that xautolock did. The latest and greatest + * xlocks also have a -resetsaver option for this very + * reason. You may want to upgrade. + */ + if (resetSaver) (void) XResetScreenSaver(d); + + setLockTrigger (lockTime); + (void) XSync (d,0); + } + + /* + * Once the locker is running, all that needs to be done is to + * set the killTrigger if needed. Notice that this must be done + * even if we actually failed to start the locker. Otherwise + * the error would "propagate" from one feature to another. + */ + if (killerSpecified) setKillTrigger (killTime); + + useRedelay = False; + } + + lockNow = False; + } +} +#endif |