summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opiecore/device/odevice.cpp623
-rw-r--r--libopie2/opiecore/device/odevice.h329
-rw-r--r--libopie2/opiecore/device/odevice_ipaq.cpp524
-rw-r--r--libopie2/opiecore/device/odevice_jornada.cpp214
-rw-r--r--libopie2/opiecore/device/odevice_ramses.cpp317
-rw-r--r--libopie2/opiecore/device/odevice_simpad.cpp443
-rw-r--r--libopie2/opiecore/device/odevice_yopy.cpp212
-rw-r--r--libopie2/opiecore/device/odevice_zaurus.cpp790
-rw-r--r--libopie2/opiecore/device/odevicebutton.cpp246
-rw-r--r--libopie2/opiecore/device/odevicebutton.h108
-rw-r--r--libopie2/opiecore/libopiecore2.control2
-rw-r--r--libopie2/opiecore/opiecore.pro16
-rw-r--r--libopie2/opiecore/oprocctrl.cpp284
-rw-r--r--libopie2/opiecore/oprocctrl.h121
-rw-r--r--libopie2/opiecore/oprocess.cpp970
-rw-r--r--libopie2/opiecore/oprocess.h747
-rw-r--r--libopie2/opienet/libopienet2.control4
17 files changed, 5946 insertions, 4 deletions
diff --git a/libopie2/opiecore/device/odevice.cpp b/libopie2/opiecore/device/odevice.cpp
new file mode 100644
index 0000000..0f88c3c
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice.cpp
@@ -0,0 +1,623 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class iPAQ;
+class Zaurus;
+class SIMpad;
+class Ramses;
+class Jornada;
+
+ODevice *ODevice::inst()
+{
+ static ODevice *dev = 0;
+
+ // rewrite this to only use /proc/devinfo or so
+
+ /*
+ if ( !dev ) {
+ if ( QFile::exists ( "/proc/hal/model" ))
+ dev = new iPAQ();
+ else if ( Zaurus::isZaurus() )
+ dev = new Zaurus();
+ else if ( QFile::exists ( "/proc/ucb1x00" ) && QFile::exists ( "/proc/cs3" ))
+ dev = new SIMpad();
+ else if ( QFile::exists ( "/proc/sys/board/name" ))
+ dev = new Ramses();
+ else if ( Yopy::isYopy() )
+ dev = new Yopy();
+ else if ( Jornada::isJornada() )
+ dev = new Jornada();
+ else
+ dev = new ODevice();
+ dev->init();
+ }
+ */
+ return dev;
+}
+
+ODevice::ODevice()
+{
+ d = new ODeviceData;
+
+ d->m_modelstr = "Unknown";
+ d->m_model = Model_Unknown;
+ d->m_vendorstr = "Unknown";
+ d->m_vendor = Vendor_Unknown;
+ d->m_systemstr = "Unknown";
+ d->m_system = System_Unknown;
+ d->m_sysverstr = "0.0";
+ d->m_rotation = Rot0;
+ d->m_direction = CW;
+
+ d->m_holdtime = 1000; // 1000ms
+ d->m_buttons = 0;
+ d->m_cpu_frequencies = new QStrList;
+}
+
+void ODevice::systemMessage ( const QCString &msg, const QByteArray & )
+{
+ if ( msg == "deviceButtonMappingChanged()" ) {
+ reloadButtonMapping();
+ }
+}
+
+void ODevice::init()
+{
+}
+
+/**
+* This method initialises the button mapping
+*/
+void ODevice::initButtons()
+{
+ if ( d->m_buttons )
+ return;
+
+ qDebug ( "init Buttons" );
+ d->m_buttons = new QValueList <ODeviceButton>;
+
+ reloadButtonMapping();
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
+}
+
+ODevice::~ODevice()
+{
+// we leak m_devicebuttons and m_cpu_frequency
+// but it's a singleton and it is not so importantant
+// -zecke
+ delete d;
+}
+
+bool ODevice::setSoftSuspend ( bool /*soft*/ )
+{
+ return false;
+}
+
+//#include <linux/apm_bios.h>
+
+#define APM_IOC_SUSPEND OD_IO( 'A', 2 )
+
+/**
+* This method will try to suspend the device
+* It only works if the user is the QWS Server and the apm application
+* is installed.
+* It tries to suspend and then waits some time cause some distributions
+* do have asynchronus apm implementations.
+* This method will either fail and return false or it'll suspend the
+* device and return once the device got woken up
+*
+* @return if the device got suspended
+*/
+bool ODevice::suspend()
+{
+ qDebug("ODevice::suspend");
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ if ( d->m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs, tvn;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync(); // flush fs caches
+ res = ( ::system ( "apm --suspend" ) == 0 );
+
+ // This is needed because the iPAQ apm implementation is asynchronous and we
+ // can not be sure when exactly the device is really suspended
+ // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
+
+ if ( res ) {
+ do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
+ ::usleep ( 200 * 1000 );
+ ::gettimeofday ( &tvn, 0 );
+ } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 1500 );
+ }
+
+ return res;
+}
+
+//#include <linux/fb.h> better not rely on kernel headers in userspace ...
+
+#define FBIOBLANK OD_IO( 'F', 0x11 ) // 0x4611
+
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING 0
+#define VESA_VSYNC_SUSPEND 1
+#define VESA_HSYNC_SUSPEND 2
+#define VESA_POWERDOWN 3
+
+/**
+* This sets the display on or off
+*/
+bool ODevice::setDisplayStatus ( bool on )
+{
+ qDebug("ODevice::setDisplayStatus(%d)", on);
+
+ if ( d->m_model == Model_Unknown )
+ return false;
+
+ bool res = false;
+ int fd;
+
+ if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) {
+ res = ( ::ioctl ( fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+/**
+* This sets the display brightness
+*
+* @param p The brightness to be set on a scale from 0 to 255
+* @return success or failure
+*/
+bool ODevice::setDisplayBrightness ( int p)
+{
+ Q_UNUSED( p )
+ return false;
+}
+
+/**
+* @return returns the number of steppings on the brightness slider
+* in the Light-'n-Power settings.
+*/
+int ODevice::displayBrightnessResolution() const
+{
+ return 16;
+}
+
+/**
+* This sets the display contrast
+* @param p The contrast to be set on a scale from 0 to 255
+* @return success or failure
+*/
+bool ODevice::setDisplayContrast ( int p)
+{
+ Q_UNUSED( p )
+ return false;
+}
+
+/**
+* @return return the max value for the brightness settings slider
+* or 0 if the device doesn't support setting of a contrast
+*/
+int ODevice::displayContrastResolution() const
+{
+ return 0;
+}
+
+/**
+* This returns the vendor as string
+* @return Vendor as QString
+*/
+QString ODevice::vendorString() const
+{
+ return d->m_vendorstr;
+}
+
+/**
+* This returns the vendor as one of the values of OVendor
+* @return OVendor
+*/
+OVendor ODevice::vendor() const
+{
+ return d->m_vendor;
+}
+
+/**
+* This returns the model as a string
+* @return A string representing the model
+*/
+QString ODevice::modelString() const
+{
+ return d->m_modelstr;
+}
+
+/**
+* This does return the OModel used
+*/
+OModel ODevice::model() const
+{
+ return d->m_model;
+}
+
+/**
+* This does return the systen name
+*/
+QString ODevice::systemString() const
+{
+ return d->m_systemstr;
+}
+
+/**
+* Return System as OSystem value
+*/
+OSystem ODevice::system() const
+{
+ return d->m_system;
+}
+
+/**
+* @return the version string of the base system
+*/
+QString ODevice::systemVersionString() const
+{
+ return d->m_sysverstr;
+}
+
+/**
+* @return the current Transformation
+*/
+Transformation ODevice::rotation() const
+{
+ return d->m_rotation;
+}
+
+/**
+* @return the current rotation direction
+*/
+ODirection ODevice::direction() const
+{
+ return d->m_direction;
+}
+
+/**
+* This plays an alarmSound
+*/
+void ODevice::alarmSound()
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+
+ if ( snd. isFinished())
+ snd. play();
+#endif
+}
+
+/**
+* This plays a key sound
+*/
+void ODevice::keySound()
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "keysound" );
+
+ if ( snd. isFinished())
+ snd. play();
+#endif
+}
+
+/**
+* This plays a touch sound
+*/
+void ODevice::touchSound()
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "touchsound" );
+
+ if ( snd. isFinished())
+ snd. play();
+#endif
+}
+
+/**
+* This method will return a list of leds
+* available on this device
+* @return a list of LEDs.
+*/
+QValueList <OLed> ODevice::ledList() const
+{
+ return QValueList <OLed>();
+}
+
+/**
+* This does return the state of the LEDs
+*/
+QValueList <OLedState> ODevice::ledStateList ( OLed /*which*/ ) const
+{
+ return QValueList <OLedState>();
+}
+
+/**
+* @return the state for a given OLed
+*/
+OLedState ODevice::ledState ( OLed /*which*/ ) const
+{
+ return Led_Off;
+}
+
+/**
+* Set the state for a LED
+* @param which Which OLed to use
+* @param st The state to set
+* @return success or failure
+*/
+bool ODevice::setLedState ( OLed which, OLedState st )
+{
+ Q_UNUSED( which )
+ Q_UNUSED( st )
+ return false;
+}
+
+/**
+* @return if the device has a light sensor
+*/
+bool ODevice::hasLightSensor() const
+{
+ return false;
+}
+
+/**
+* @return a value from the light sensor
+*/
+int ODevice::readLightSensor()
+{
+ return -1;
+}
+
+/**
+* @return the light sensor resolution
+*/
+int ODevice::lightSensorResolution() const
+{
+ return 0;
+}
+
+/**
+* @return if the device has a hinge sensor
+*/
+bool ODevice::hasHingeSensor() const
+{
+ return false;
+}
+
+/**
+* @return a value from the hinge sensor
+*/
+OHingeStatus ODevice::readHingeSensor()
+{
+ return CASE_UNKNOWN;
+}
+
+/**
+* @return a list with CPU frequencies supported by the hardware
+*/
+const QStrList &ODevice::allowedCpuFrequencies() const
+{
+ return *d->m_cpu_frequencies;
+}
+
+
+/**
+* Set desired CPU frequency
+*
+* @param index index into d->m_cpu_frequencies of the frequency to be set
+*/
+bool ODevice::setCurrentCpuFrequency(uint index)
+{
+ if (index >= d->m_cpu_frequencies->count())
+ return false;
+
+ char *freq = d->m_cpu_frequencies->at(index);
+ qWarning("set freq to %s", freq);
+
+ int fd;
+
+ if ((fd = ::open("/proc/sys/cpu/0/speed", O_WRONLY)) >= 0) {
+ char writeCommand[50];
+ const int count = sprintf(writeCommand, "%s\n", freq);
+ int res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ return res;
+ }
+
+ return false;
+}
+
+
+/**
+* @return a list of hardware buttons
+*/
+const QValueList <ODeviceButton> &ODevice::buttons()
+{
+ initButtons();
+
+ return *d->m_buttons;
+}
+
+/**
+* @return The amount of time that would count as a hold
+*/
+uint ODevice::buttonHoldTime() const
+{
+ return d->m_holdtime;
+}
+
+/**
+* This method return a ODeviceButton for a key code
+* or 0 if no special hardware button is available for the device
+*
+* @return The devicebutton or 0l
+* @see ODeviceButton
+*/
+const ODeviceButton *ODevice::buttonForKeycode ( ushort code )
+{
+ initButtons();
+
+ for ( QValueListConstIterator<ODeviceButton> it = d->m_buttons->begin(); it != d->m_buttons->end(); ++it ) {
+ if ( (*it). keycode() == code )
+ return &(*it);
+ }
+ return 0;
+}
+
+void ODevice::reloadButtonMapping()
+{
+ initButtons();
+
+ Config cfg ( "ButtonSettings" );
+
+ for ( uint i = 0; i < d->m_buttons->count(); i++ ) {
+ ODeviceButton &b = ( *d->m_buttons ) [i];
+ QString group = "Button" + QString::number ( i );
+
+ QCString pch, hch;
+ QCString pm, hm;
+ QByteArray pdata, hdata;
+
+ if ( cfg. hasGroup ( group )) {
+ cfg. setGroup ( group );
+ pch = cfg. readEntry ( "PressedActionChannel" ). latin1();
+ pm = cfg. readEntry ( "PressedActionMessage" ). latin1();
+ // pdata = decodeBase64 ( buttonFile. readEntry ( "PressedActionArgs" ));
+
+ hch = cfg. readEntry ( "HeldActionChannel" ). latin1();
+ hm = cfg. readEntry ( "HeldActionMessage" ). latin1();
+ // hdata = decodeBase64 ( buttonFile. readEntry ( "HeldActionArgs" ));
+ }
+
+ b. setPressedAction ( OQCopMessage ( pch, pm, pdata ));
+
+ b. setHeldAction ( OQCopMessage ( hch, hm, hdata ));
+ }
+}
+
+void ODevice::remapPressedAction ( int button, const OQCopMessage &action )
+{
+ initButtons();
+
+ QString mb_chan;
+
+ if ( button >= (int) d->m_buttons->count())
+ return;
+
+ ODeviceButton &b = ( *d->m_buttons ) [button];
+ b. setPressedAction ( action );
+
+ mb_chan=b. pressedAction(). channel();
+
+ Config buttonFile ( "ButtonSettings" );
+ buttonFile. setGroup ( "Button" + QString::number ( button ));
+ buttonFile. writeEntry ( "PressedActionChannel", (const char*) mb_chan);
+ buttonFile. writeEntry ( "PressedActionMessage", (const char*) b. pressedAction(). message());
+
+// buttonFile. writeEntry ( "PressedActionArgs", encodeBase64 ( b. pressedAction(). data()));
+
+ QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
+}
+
+void ODevice::remapHeldAction ( int button, const OQCopMessage &action )
+{
+ initButtons();
+
+ if ( button >= (int) d->m_buttons->count())
+ return;
+
+ ODeviceButton &b = ( *d->m_buttons ) [button];
+ b. setHeldAction ( action );
+
+ Config buttonFile ( "ButtonSettings" );
+ buttonFile. setGroup ( "Button" + QString::number ( button ));
+ buttonFile. writeEntry ( "HeldActionChannel", (const char *) b. heldAction(). channel());
+ buttonFile. writeEntry ( "HeldActionMessage", (const char *) b. heldAction(). message());
+
+// buttonFile. writeEntry ( "HeldActionArgs", decodeBase64 ( b. heldAction(). data()));
+
+ QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
+}
+void ODevice::virtual_hook(int, void* ){
+
+}
diff --git a/libopie2/opiecore/device/odevice.h b/libopie2/opiecore/device/odevice.h
new file mode 100644
index 0000000..bde6411
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice.h
@@ -0,0 +1,329 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ODEVICE_H_
+#define ODEVICE_H_
+
+#include <opie2/odevicebutton.h>
+
+/* QT */
+#include <qnamespace.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qstrlist.h>
+
+#include <qpe/qpeapplication.h> /* for Transformation enum.. */
+
+namespace Opie
+{
+ class ODeviceData;
+/**
+ * The available devices
+ */
+enum OModel {
+ Model_Unknown, // = 0
+
+ Model_Series_Mask = 0xff000000,
+
+ Model_iPAQ = ( 1 << 24 ),
+
+ Model_iPAQ_All = ( Model_iPAQ | 0xffffff ),
+ Model_iPAQ_H31xx = ( Model_iPAQ | 0x000001 ),
+ Model_iPAQ_H36xx = ( Model_iPAQ | 0x000002 ),
+ Model_iPAQ_H37xx = ( Model_iPAQ | 0x000004 ),
+ Model_iPAQ_H38xx = ( Model_iPAQ | 0x000008 ),
+ Model_iPAQ_H39xx = ( Model_iPAQ | 0x000010 ),
+ Model_iPAQ_H5xxx = ( Model_iPAQ | 0x000011 ),
+
+ Model_Jornada = ( 6 << 24 ),
+ Model_Jornada_56x = ( Model_Jornada | 0x000001 ),
+
+ Model_Zaurus = ( 2 << 24 ),
+
+ Model_Zaurus_SL5000 = ( Model_Zaurus | 0x000001 ),
+ Model_Zaurus_SL5500 = ( Model_Zaurus | 0x000002 ),
+ Model_Zaurus_SLA300 = ( Model_Zaurus | 0x000003 ),
+ Model_Zaurus_SLB600 = ( Model_Zaurus | 0x000004 ),
+ Model_Zaurus_SLC7x0 = ( Model_Zaurus | 0x000005 ),
+
+ Model_SIMpad = ( 3 << 24 ),
+
+ Model_SIMpad_All = ( Model_SIMpad | 0xffffff ),
+ Model_SIMpad_CL4 = ( Model_SIMpad | 0x000001 ),
+ Model_SIMpad_SL4 = ( Model_SIMpad | 0x000002 ),
+ Model_SIMpad_SLC = ( Model_SIMpad | 0x000004 ),
+ Model_SIMpad_TSinus = ( Model_SIMpad | 0x000008 ),
+
+ Model_Ramses = ( 4 << 24 ),
+
+ Model_Ramses_All = ( Model_Ramses | 0xffffff ),
+ Model_Ramses_MNCI = ( Model_Ramses | 0x000001 ),
+
+ Model_Yopy = ( 5 << 24 ),
+
+ Model_Yopy_All = ( Model_Yopy | 0xffffff ),
+ Model_Yopy_3000 = ( Model_Yopy | 0x000001 ),
+ Model_Yopy_3500 = ( Model_Yopy | 0x000002 ),
+ Model_Yopy_3700 = ( Model_Yopy | 0x000003 ),
+
+};
+
+/**
+ * The vendor of the device
+ */
+enum OVendor {
+ Vendor_Unknown,
+
+ Vendor_HP,
+ Vendor_Sharp,
+ Vendor_SIEMENS,
+ Vendor_MundN,
+ Vendor_GMate,
+};
+
+/**
+ * The System used
+ */
+enum OSystem {
+ System_Unknown,
+
+ System_Familiar,
+ System_Zaurus,
+ System_OpenZaurus,
+ System_Linupy,
+};
+
+enum OLedState {
+ Led_Off,
+ Led_On,
+ Led_BlinkSlow,
+ Led_BlinkFast
+};
+
+enum OLed {
+ Led_Mail,
+ Led_Power,
+ Led_BlueTooth
+};
+
+enum OHardKey {
+ HardKey_Datebook = Qt::Key_F9,
+ HardKey_Contacts = Qt::Key_F10,
+ HardKey_Menu = Qt::Key_F11,
+ HardKey_Home = Qt::Key_F12,
+ HardKey_Mail = Qt::Key_F13,
+ HardKey_Record = Qt::Key_F24,
+ HardKey_Suspend = Qt::Key_F34,
+ HardKey_Backlight = Qt::Key_F35,
+ HardKey_Action = Qt::Key_F10,
+ HardKey_OK = Qt::Key_F11,
+ HardKey_End = Qt::Key_F12,
+};
+
+enum ODirection {
+ CW = 0,
+ CCW = 1,
+ Flip = 2,
+};
+
+enum OHingeStatus {
+ CASE_CLOSED = 3,
+ CASE_PORTRAIT = 2,
+ CASE_LANDSCAPE = 0,
+ CASE_UNKNOWN = 1,
+};
+
+/**
+ * A singleton which gives informations about device specefic option
+ * like the Hardware used, LEDs, the Base Distribution and
+ * hardware key mappings.
+ *
+ * @short A small class for device specefic options
+ * @see QObject
+ * @author Robert Griebl
+ * @version 1.0
+ */
+class ODevice : public QObject
+{
+ Q_OBJECT
+
+private:
+ /* disable copy */
+ ODevice ( const ODevice & );
+
+protected:
+ ODevice();
+ virtual void init();
+ virtual void initButtons();
+
+ ODeviceData *d;
+
+public:
+ // sandman do we want to allow destructions? -zecke?
+ virtual ~ODevice();
+
+ static ODevice *inst();
+
+ // information
+
+ QString modelString() const;
+ OModel model() const;
+ inline OModel series() const { return (OModel) ( model() & Model_Series_Mask ); }
+
+ QString vendorString() const;
+ OVendor vendor() const;
+
+ QString systemString() const;
+ OSystem system() const;
+
+ QString systemVersionString() const;
+
+ virtual Transformation rotation() const;
+ virtual ODirection direction() const;
+
+ // system
+
+ virtual bool setSoftSuspend ( bool on );
+ virtual bool suspend();
+
+ virtual bool setDisplayStatus ( bool on );
+ virtual bool setDisplayBrightness ( int brightness );
+ virtual int displayBrightnessResolution() const;
+ virtual bool setDisplayContrast ( int contrast );
+ virtual int displayContrastResolution() const;
+
+ // don't add new virtual methods, use this:
+ // /*virtual */ void boo(int i ) { return virtual_hook(1,&i); };
+ // and in your subclass do do overwrite
+ // protected virtual int virtual_hook(int, void *)
+ // which is defined below
+
+ // input / output
+ //FIXME playAlarmSound and al might be better -zecke
+ virtual void alarmSound();
+ virtual void keySound();
+ virtual void touchSound();
+
+ virtual QValueList <OLed> ledList() const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState ( OLed led ) const;
+ virtual bool setLedState ( OLed led, OLedState st );
+
+ virtual bool hasLightSensor() const;
+ virtual int readLightSensor();
+ virtual int lightSensorResolution() const;
+
+ virtual bool hasHingeSensor() const;
+ virtual OHingeStatus readHingeSensor();
+
+ const QStrList &allowedCpuFrequencies() const;
+ bool setCurrentCpuFrequency(uint index);
+
+ /**
+ * Returns the available buttons on this device. The number and location
+ * of buttons will vary depending on the device. Button numbers will be assigned
+ * by the device manufacturer and will be from most preferred button to least preffered
+ * button. Note that this list only contains "user mappable" buttons.
+ */
+ const QValueList<ODeviceButton> &buttons() /* ### make const */;
+
+ /**
+ * Returns the DeviceButton for the \a keyCode. If \a keyCode is not found, it
+ * returns 0L
+ */
+ const ODeviceButton *buttonForKeycode ( ushort keyCode );
+
+ /**
+ * Reassigns the pressed action for \a button. To return to the factory
+ * default pass an empty string as \a qcopMessage.
+ */
+ void remapPressedAction ( int button, const OQCopMessage &qcopMessage );
+
+ /**
+ * Reassigns the held action for \a button. To return to the factory
+ * default pass an empty string as \a qcopMessage.
+ */
+ void remapHeldAction ( int button, const OQCopMessage &qcopMessage );
+
+ /**
+ * How long (in ms) you have to press a button for a "hold" action
+ */
+ uint buttonHoldTime() const;
+
+signals:
+ void buttonMappingChanged();
+
+private slots:
+ void systemMessage ( const QCString &, const QByteArray & );
+
+protected:
+ void reloadButtonMapping();
+ /* ugly virtual hook */
+ virtual void virtual_hook( int id, void* data );
+};
+
+class ODeviceData {
+
+ public:
+ QString m_vendorstr;
+ OVendor m_vendor;
+
+ QString m_modelstr;
+ OModel m_model;
+
+ QString m_systemstr;
+ OSystem m_system;
+
+ QString m_sysverstr;
+
+ Transformation m_rotation;
+ ODirection m_direction;
+
+ QValueList <ODeviceButton> *m_buttons;
+ uint m_holdtime;
+ QStrList *m_cpu_frequencies;
+};
+
+}
+
+static inline bool isQWS()
+{
+ return qApp ? ( qApp->type() == QApplication::GuiServer ) : false;
+}
+
+static QCString makeChannel ( const char *str )
+{
+ if ( str && !::strchr ( str, '/' ))
+ return QCString ( "QPE/Application/" ) + str;
+ else
+ return str;
+}
+
+#endif
+
diff --git a/libopie2/opiecore/device/odevice_ipaq.cpp b/libopie2/opiecore/device/odevice_ipaq.cpp
new file mode 100644
index 0000000..d928806
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_ipaq.cpp
@@ -0,0 +1,524 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+typedef struct {
+ unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */
+ unsigned char TotalTime; /* Units of 5 seconds */
+ unsigned char OnTime; /* units of 100m/s */
+ unsigned char OffTime; /* units of 100m/s */
+} LED_IN;
+
+typedef struct {
+ unsigned char mode;
+ unsigned char pwr;
+ unsigned char brightness;
+} FLITE_IN;
+
+#define LED_ON OD_IOW( 'f', 5, LED_IN )
+#define FLITE_ON OD_IOW( 'f', 7, FLITE_IN )
+
+using namespace Opie;
+
+class iPAQ : public ODevice, public QWSServer::KeyboardFilter
+{
+
+ protected:
+ virtual void init();
+ virtual void initButtons();
+
+ public:
+ virtual bool setSoftSuspend( bool soft );
+
+ virtual bool setDisplayBrightness( int b );
+ virtual int displayBrightnessResolution() const;
+
+ virtual void alarmSound();
+
+ virtual QValueList <OLed> ledList() const;
+ virtual QValueList <OLedState> ledStateList( OLed led ) const;
+ virtual OLedState ledState( OLed led ) const;
+ virtual bool setLedState( OLed led, OLedState st );
+
+ virtual bool hasLightSensor() const;
+ virtual int readLightSensor();
+ virtual int lightSensorResolution() const;
+
+ protected:
+ virtual bool filter( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent( QTimerEvent *te );
+
+ int m_power_timer;
+
+ OLedState m_leds [2];
+};
+
+struct i_button {
+ uint model;
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} ipaq_buttons [] = {
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/ipaq_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/ipaq_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx,
+ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/ipaq_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
+ "devicebuttons/ipaq_mail",
+ "mail", "raise()",
+ "mail", "newMail()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/ipaq_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
+ "devicebuttons/ipaq_record",
+ "QPE/VMemo", "toggleRecord()",
+ "sound", "raise()" },
+};
+
+void iPAQ::init()
+{
+ d->m_vendorstr = "HP";
+ d->m_vendor = Vendor_HP;
+
+ QFile f ( "/proc/hal/model" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+
+ d->m_modelstr = "H" + ts. readLine();
+
+ if ( d->m_modelstr == "H3100" )
+ d->m_model = Model_iPAQ_H31xx;
+ else if ( d->m_modelstr == "H3600" )
+ d->m_model = Model_iPAQ_H36xx;
+ else if ( d->m_modelstr == "H3700" )
+ d->m_model = Model_iPAQ_H37xx;
+ else if ( d->m_modelstr == "H3800" )
+ d->m_model = Model_iPAQ_H38xx;
+ else if ( d->m_modelstr == "H3900" )
+ d->m_model = Model_iPAQ_H39xx;
+ else if ( d->m_modelstr == "H5400" )
+ d->m_model = Model_iPAQ_H5xxx;
+ else
+ d->m_model = Model_Unknown;
+
+ f. close();
+ }
+
+ switch ( d->m_model ) {
+ case Model_iPAQ_H31xx:
+ case Model_iPAQ_H38xx:
+ d->m_rotation = Rot90;
+ break;
+ case Model_iPAQ_H36xx:
+ case Model_iPAQ_H37xx:
+ case Model_iPAQ_H39xx:
+
+ default:
+ d->m_rotation = Rot270;
+ break;
+ case Model_iPAQ_H5xxx:
+ d->m_rotation = Rot0;
+ }
+
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+ d->m_systemstr = "Familiar";
+ d->m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ d->m_sysverstr = ts. readLine(). mid ( 10 );
+
+ f. close();
+ } else {
+ f. setName ( "/etc/oz_version" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ d->m_systemstr = "OpenEmbedded/iPaq";
+ d->m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ ts.setDevice ( &f );
+ d->m_sysverstr = ts. readLine();
+ f. close();
+ }
+ }
+
+ m_leds [0] = m_leds [1] = Led_Off;
+
+ m_power_timer = 0;
+
+}
+
+void iPAQ::initButtons()
+{
+ if ( d->m_buttons )
+ return;
+
+ if ( isQWS( ) )
+ QWSServer::setKeyboardFilter ( this );
+
+ d->m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
+ i_button *ib = ipaq_buttons + i;
+ ODeviceButton b;
+
+ if (( ib->model & d->m_model ) == d->m_model ) {
+ b. setKeycode ( ib->code );
+ b. setUserText ( QObject::tr ( "Button", ib->utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib->pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib->fpressedservice ), ib->fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib->fheldservice ), ib->fheldaction ));
+
+ d->m_buttons->append ( b );
+ }
+ }
+ reloadButtonMapping();
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
+}
+
+QValueList <OLed> iPAQ::ledList() const
+{
+ QValueList <OLed> vl;
+ vl << Led_Power;
+
+ if ( d->m_model == Model_iPAQ_H38xx )
+ vl << Led_BlueTooth;
+ return vl;
+}
+
+QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Power )
+ vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast;
+ else if ( l == Led_BlueTooth && d->m_model == Model_iPAQ_H38xx )
+ vl << Led_Off; // << Led_On << ???
+
+ return vl;
+}
+
+OLedState iPAQ::ledState ( OLed l ) const
+{
+ switch ( l ) {
+ case Led_Power:
+ return m_leds [0];
+ case Led_BlueTooth:
+ return m_leds [1];
+ default:
+ return Led_Off;
+ }
+}
+
+bool iPAQ::setLedState ( OLed l, OLedState st )
+{
+ static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK );
+
+ if ( l == Led_Power ) {
+ if ( fd >= 0 ) {
+ LED_IN leds;
+ ::memset ( &leds, 0, sizeof( leds ));
+ leds. TotalTime = 0;
+ leds. OnTime = 0;
+ leds. OffTime = 1;
+ leds. OffOnBlink = 2;
+
+ switch ( st ) {
+ case Led_Off : leds. OffOnBlink = 0; break;
+ case Led_On : leds. OffOnBlink = 1; break;
+ case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
+ case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
+ }
+
+ if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) {
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
+{
+ int newkeycode = keycode;
+
+ switch ( keycode ) {
+ // H38xx/H39xx have no "Q" key anymore - this is now the Mail key
+ case HardKey_Menu: {
+ if (( d->m_model == Model_iPAQ_H38xx ) ||
+ ( d->m_model == Model_iPAQ_H39xx ) ||
+ ( d->m_model == Model_iPAQ_H5xxx)) {
+ newkeycode = HardKey_Mail;
+ }
+ break;
+ }
+
+ // Rotate cursor keys 180°
+ case Key_Left :
+ case Key_Right:
+ case Key_Up :
+ case Key_Down : {
+ if (( d->m_model == Model_iPAQ_H31xx ) ||
+ ( d->m_model == Model_iPAQ_H38xx )) {
+ newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4;
+ }
+ break;
+ }
+
+ // map Power Button short/long press to F34/F35
+ case Key_SysReq: {
+ if ( isPress ) {
+ if ( m_power_timer )
+ killTimer ( m_power_timer );
+ m_power_timer = startTimer ( 500 );
+ }
+ else if ( m_power_timer ) {
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false );
+ }
+ newkeycode = Key_unknown;
+ break;
+ }
+ }
+
+ if ( newkeycode != keycode ) {
+ if ( newkeycode != Key_unknown )
+ QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
+ return true;
+ }
+ else
+ return false;
+}
+
+void iPAQ::timerEvent ( QTimerEvent * )
+{
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
+}
+
+
+void iPAQ::alarmSound()
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play();
+ while ( !snd. isFinished())
+ qApp->processEvents();
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+#endif
+}
+
+
+bool iPAQ::setSoftSuspend ( bool soft )
+{
+ bool res = false;
+ int fd;
+
+ if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
+ if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
+ res = true;
+ else
+ ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
+
+ ::close ( fd );
+ }
+ else
+ ::perror ( "/proc/sys/ts/suspend_button_mode" );
+
+ return res;
+}
+
+
+bool iPAQ::setDisplayBrightness ( int bright )
+{
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 0 )
+ bright = 0;
+
+ if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
+ FLITE_IN bl;
+ bl. mode = 1;
+ bl. pwr = bright ? 1 : 0;
+ bl. brightness = ( bright * ( displayBrightnessResolution() - 1 ) + 127 ) / 255;
+ res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+int iPAQ::displayBrightnessResolution() const
+{
+ switch ( model()) {
+ case Model_iPAQ_H31xx:
+ case Model_iPAQ_H36xx:
+ case Model_iPAQ_H37xx:
+ return 128; // really 256, but >128 could damage the LCD
+
+ case Model_iPAQ_H38xx:
+ case Model_iPAQ_H39xx:
+ return 64;
+ case Model_iPAQ_H5xxx:
+ return 255;
+
+ default:
+ return 2;
+ }
+}
+
+
+bool iPAQ::hasLightSensor() const
+{
+ return true;
+}
+
+int iPAQ::readLightSensor()
+{
+ int fd;
+ int val = -1;
+
+ if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) {
+ char buffer [8];
+
+ if ( ::read ( fd, buffer, 5 ) == 5 ) {
+ char *endptr;
+
+ buffer [4] = 0;
+ val = ::strtol ( buffer + 2, &endptr, 16 );
+
+ if ( *endptr != 0 )
+ val = -1;
+ }
+ ::close ( fd );
+ }
+
+ return val;
+}
+
+int iPAQ::lightSensorResolution() const
+{
+ return 256;
+}
diff --git a/libopie2/opiecore/device/odevice_jornada.cpp b/libopie2/opiecore/device/odevice_jornada.cpp
new file mode 100644
index 0000000..bcd03ed
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_jornada.cpp
@@ -0,0 +1,214 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+typedef struct {
+ unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */
+ unsigned char TotalTime; /* Units of 5 seconds */
+ unsigned char OnTime; /* units of 100m/s */
+ unsigned char OffTime; /* units of 100m/s */
+} LED_IN;
+
+typedef struct {
+ unsigned char mode;
+ unsigned char pwr;
+ unsigned char brightness;
+} FLITE_IN;
+
+#define LED_ON OD_IOW( 'f', 5, LED_IN )
+#define FLITE_ON OD_IOW( 'f', 7, FLITE_IN )
+
+using namespace Opie;
+
+class Jornada : public ODevice
+{
+
+ protected:
+ virtual void init();
+
+ public:
+ virtual bool setSoftSuspend ( bool soft );
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution() const;
+ static bool isJornada();
+};
+
+
+bool Jornada::isJornada()
+{
+ QFile f( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine() ) {
+ if ( line. left ( 8 ) == "Hardware" ) {
+ int loc = line. find ( ":" );
+ if ( loc != -1 ) {
+ QString model = line.mid( loc + 2 ).simplifyWhiteSpace( );
+ return ( model == "HP Jornada 56x" );
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void Jornada::init()
+{
+ d->m_vendorstr = "HP";
+ d->m_vendor = Vendor_HP;
+ d->m_modelstr = "Jornada 56x";
+ d->m_model = Model_Jornada_56x;
+ d->m_systemstr = "Familiar";
+ d->m_system = System_Familiar;
+ d->m_rotation = Rot0;
+
+ QFile f ( "/etc/familiar-version" );
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+
+ QTextStream ts ( &f );
+ d->m_sysverstr = ts. readLine(). mid ( 10 );
+
+ f. close();
+ }
+}
+
+#if 0
+void Jornada::initButtons()
+{
+ if ( d->m_buttons )
+ return;
+
+ // Simulation uses iPAQ 3660 device buttons
+
+ qDebug ( "init Buttons" );
+ d->m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
+ i_button *ib = ipaq_buttons + i;
+ ODeviceButton b;
+
+ if (( ib->model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) {
+ b. setKeycode ( ib->code );
+ b. setUserText ( QObject::tr ( "Button", ib->utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib->pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib->fpressedservice ), ib->fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib->fheldservice ), ib->fheldaction ));
+ d->m_buttons->append ( b );
+ }
+ }
+ reloadButtonMapping();
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
+}
+#endif
+
+int Jornada::displayBrightnessResolution() const
+{
+}
+
+bool Jornada::setDisplayBrightness( int bright )
+{
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 0 )
+ bright = 0;
+
+ if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
+ FLITE_IN bl;
+ bl. mode = 1;
+ bl. pwr = bright ? 1 : 0;
+ bl. brightness = ( bright * ( displayBrightnessResolution() - 1 ) + 127 ) / 255;
+ res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+bool Jornada::setSoftSuspend( bool soft )
+{
+ bool res = false;
+ int fd;
+
+ if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
+ if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
+ res = true;
+ else
+ ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
+
+ ::close ( fd );
+ }
+ else
+ ::perror ( "/proc/sys/ts/suspend_button_mode" );
+
+ return res;
+}
diff --git a/libopie2/opiecore/device/odevice_ramses.cpp b/libopie2/opiecore/device/odevice_ramses.cpp
new file mode 100644
index 0000000..a90c3a0
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_ramses.cpp
@@ -0,0 +1,317 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class Ramses : public ODevice, public QWSServer::KeyboardFilter
+{
+ protected:
+ virtual void init();
+
+ public:
+ virtual bool setSoftSuspend( bool soft );
+ virtual bool suspend();
+
+ virtual bool setDisplayStatus( bool on );
+ virtual bool setDisplayBrightness( int b );
+ virtual int displayBrightnessResolution() const;
+ virtual bool setDisplayContrast( int b );
+ virtual int displayContrastResolution() const;
+
+ protected:
+ virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent ( QTimerEvent *te );
+
+ int m_power_timer;
+};
+
+struct r_button {
+ uint model;
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} ramses_buttons [] = {
+ { Model_Ramses_MNCI,
+ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/z_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_Ramses_MNCI,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/ipaq_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+};
+
+void Ramses::init()
+{
+ d->m_vendorstr = "M und N";
+ d->m_vendor = Vendor_MundN;
+
+ QFile f("/proc/sys/board/ramses");
+
+ d->m_modelstr = "Ramses";
+ d->m_model = Model_Ramses_MNCI;
+
+ d->m_rotation = Rot0;
+ d->m_holdtime = 1000;
+
+ f.setName("/etc/oz_version");
+
+ if (f.open(IO_ReadOnly)) {
+ d->m_systemstr = "OpenEmbedded/Ramses";
+ d->m_system = System_OpenZaurus;
+
+ QTextStream ts(&f);
+ ts.setDevice(&f);
+ d->m_sysverstr = ts.readLine();
+ f.close();
+ }
+
+ m_power_timer = 0;
+
+#ifdef QT_QWS_ALLOW_OVERCLOCK
+#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
+#define OC(x...) x
+#else
+#define OC(x...)
+#endif
+
+ // This table is true for a Intel XScale PXA 255
+
+ d->m_cpu_frequencies->append("99000"); // mem= 99, run= 99, turbo= 99, PXbus= 50
+OC(d->m_cpu_frequencies->append("118000"); ) // mem=118, run=118, turbo=118, PXbus= 59 OC'd mem
+ d->m_cpu_frequencies->append("199100"); // mem= 99, run=199, turbo=199, PXbus= 99
+OC(d->m_cpu_frequencies->append("236000"); ) // mem=118, run=236, turbo=236, PXbus=118 OC'd mem
+ d->m_cpu_frequencies->append("298600"); // mem= 99, run=199, turbo=298, PXbus= 99
+OC(d->m_cpu_frequencies->append("354000"); ) // mem=118, run=236, turbo=354, PXbus=118 OC'd mem
+ d->m_cpu_frequencies->append("398099"); // mem= 99, run=199, turbo=398, PXbus= 99
+ d->m_cpu_frequencies->append("398100"); // mem= 99, run=398, turbo=398, PXbus=196
+OC(d->m_cpu_frequencies->append("471000"); ) // mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus
+
+}
+
+bool Ramses::filter(int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat)
+{
+ Q_UNUSED( keycode );
+ Q_UNUSED( modifiers );
+ Q_UNUSED( isPress );
+ Q_UNUSED( autoRepeat );
+ return false;
+}
+
+void Ramses::timerEvent(QTimerEvent *)
+{
+ killTimer(m_power_timer);
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, true, false);
+ QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, false, false);
+}
+
+
+bool Ramses::setSoftSuspend(bool soft)
+{
+ qDebug("Ramses::setSoftSuspend(%d)", soft);
+#if 0
+ bool res = false;
+ int fd;
+
+ if (((fd = ::open("/dev/apm_bios", O_RDWR)) >= 0) ||
+ ((fd = ::open("/dev/misc/apm_bios",O_RDWR)) >= 0)) {
+
+ int sources = ::ioctl(fd, APM_IOCGEVTSRC, 0); // get current event sources
+
+ if (sources >= 0) {
+ if (soft)
+ sources &= ~APM_EVT_POWER_BUTTON;
+ else
+ sources |= APM_EVT_POWER_BUTTON;
+
+ if (::ioctl(fd, APM_IOCSEVTSRC, sources) >= 0) // set new event sources
+ res = true;
+ else
+ perror("APM_IOCGEVTSRC");
+ }
+ else
+ perror("APM_IOCGEVTSRC");
+
+ ::close(fd);
+ }
+ else
+ perror("/dev/apm_bios or /dev/misc/apm_bios");
+
+ return res;
+#else
+ return true;
+#endif
+}
+
+bool Ramses::suspend()
+{
+ qDebug("Ramses::suspend");
+ return false;
+}
+
+/**
+* This sets the display on or off
+*/
+bool Ramses::setDisplayStatus(bool on)
+{
+ qDebug("Ramses::setDisplayStatus(%d)", on);
+#if 0
+ bool res = false;
+ int fd;
+
+ if ((fd = ::open ("/dev/fb/0", O_RDWR)) >= 0) {
+ res = (::ioctl(fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN) == 0);
+ ::close(fd);
+ }
+ return res;
+#else
+ return true;
+#endif
+}
+
+
+/*
+* We get something between 0..255 into us
+*/
+bool Ramses::setDisplayBrightness(int bright)
+{
+ qDebug("Ramses::setDisplayBrightness(%d)", bright);
+ bool res = false;
+ int fd;
+
+ // pwm1 brighness: 20 steps 500..0 (dunkel->hell)
+
+ if (bright > 255 )
+ bright = 255;
+ if (bright < 0)
+ bright = 0;
+
+ // Turn backlight completely off
+ if ((fd = ::open("/proc/sys/board/lcd_backlight", O_WRONLY)) >= 0) {
+ char writeCommand[10];
+ const int count = sprintf(writeCommand, "%d\n", bright ? 1 : 0);
+ res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ }
+
+ // scale backlight brightness to hardware
+ bright = 500-(bright * 500 / 255);
+ if ((fd = ::open("/proc/sys/board/pwm1", O_WRONLY)) >= 0) {
+ qDebug(" %d ->pwm1", bright);
+ char writeCommand[100];
+ const int count = sprintf(writeCommand, "%d\n", bright);
+ res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ }
+ return res;
+}
+
+
+int Ramses::displayBrightnessResolution() const
+{
+ return 32;
+}
+
+bool Ramses::setDisplayContrast(int contr)
+{
+ qDebug("Ramses::setDisplayContrast(%d)", contr);
+ bool res = false;
+ int fd;
+
+ // pwm0 contrast: 20 steps 79..90 (dunkel->hell)
+
+ if (contr > 255 )
+ contr = 255;
+ if (contr < 0)
+ contr = 0;
+ contr = 90 - (contr * 20 / 255);
+
+ if ((fd = ::open("/proc/sys/board/pwm0", O_WRONLY)) >= 0) {
+ qDebug(" %d ->pwm0", contr);
+ char writeCommand[100];
+ const int count = sprintf(writeCommand, "%d\n", contr);
+ res = (::write(fd, writeCommand, count) != -1);
+ res = true;
+ ::close(fd);
+ }
+ return res;
+}
+
+
+int Ramses::displayContrastResolution() const
+{
+ return 20;
+}
+
diff --git a/libopie2/opiecore/device/odevice_simpad.cpp b/libopie2/opiecore/device/odevice_simpad.cpp
new file mode 100644
index 0000000..82dce10
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_simpad.cpp
@@ -0,0 +1,443 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class SIMpad : public ODevice, public QWSServer::KeyboardFilter
+{
+ protected:
+ virtual void init();
+ virtual void initButtons();
+
+ public:
+ virtual bool setSoftSuspend( bool soft );
+ virtual bool suspend();
+
+ virtual bool setDisplayStatus( bool on );
+ virtual bool setDisplayBrightness( int b );
+ virtual int displayBrightnessResolution() const;
+
+ virtual void alarmSound();
+
+ virtual QValueList <OLed> ledList() const;
+ virtual QValueList <OLedState> ledStateList( OLed led ) const;
+ virtual OLedState ledState( OLed led ) const;
+ virtual bool setLedState( OLed led, OLedState st );
+
+ protected:
+ virtual bool filter( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent( QTimerEvent *te );
+
+ int m_power_timer;
+
+ OLedState m_leds [1];
+};
+
+struct s_button {
+ uint model;
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} simpad_buttons [] = {
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Lower+Up"),
+ "devicebuttons/simpad_lower_up",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Lower+Down"),
+ "devicebuttons/simpad_lower_down",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Lower+Right"),
+ "devicebuttons/simpad_lower_right",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Lower+Left"),
+ "devicebuttons/simpad_lower_left",
+ "mail", "raise()",
+ "mail", "newMail()" },
+
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F5, QT_TRANSLATE_NOOP("Button", "Upper+Up"),
+ "devicebuttons/simpad_upper_up",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F6, QT_TRANSLATE_NOOP("Button", "Upper+Down"),
+ "devicebuttons/simpad_upper_down",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F7, QT_TRANSLATE_NOOP("Button", "Upper+Right"),
+ "devicebuttons/simpad_upper_right",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Upper+Left"),
+ "devicebuttons/simpad_upper_left",
+ "QPE/Rotation", "flip()",
+ "QPE/Rotation", "flip()" },
+ /*
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
+ "devicebuttons/simpad_lower_upper",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
+ "devicebuttons/simpad_upper_lower",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ */
+};
+
+void SIMpad::init()
+{
+ d->m_vendorstr = "SIEMENS";
+ d->m_vendor = Vendor_SIEMENS;
+
+ QFile f ( "/proc/hal/model" );
+
+ //TODO Implement model checking
+ //FIXME For now we assume an SL4
+
+ d->m_modelstr = "SL4";
+ d->m_model = Model_SIMpad_SL4;
+
+ switch ( d->m_model ) {
+ default:
+ d->m_rotation = Rot0;
+ d->m_direction = CCW;
+ d->m_holdtime = 1000; // 1000ms
+
+ break;
+ }
+
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+ d->m_systemstr = "Familiar";
+ d->m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ d->m_sysverstr = ts. readLine(). mid ( 10 );
+
+ f. close();
+ } else {
+ f. setName ( "/etc/oz_version" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ d->m_systemstr = "OpenEmbedded/SIMpad";
+ d->m_system = System_OpenZaurus;
+
+ QTextStream ts ( &f );
+ ts.setDevice ( &f );
+ d->m_sysverstr = ts. readLine();
+ f. close();
+ }
+ }
+
+ m_leds [0] = m_leds [1] = Led_Off;
+
+ m_power_timer = 0;
+
+}
+
+void SIMpad::initButtons()
+{
+ if ( d->m_buttons )
+ return;
+
+ if ( isQWS( ) )
+ QWSServer::setKeyboardFilter ( this );
+
+ d->m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( simpad_buttons ) / sizeof( s_button )); i++ ) {
+ s_button *sb = simpad_buttons + i;
+ ODeviceButton b;
+
+ if (( sb->model & d->m_model ) == d->m_model ) {
+ b. setKeycode ( sb->code );
+ b. setUserText ( QObject::tr ( "Button", sb->utext ));
+ b. setPixmap ( Resource::loadPixmap ( sb->pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( sb->fpressedservice ), sb->fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( sb->fheldservice ), sb->fheldaction ));
+
+ d->m_buttons->append ( b );
+ }
+ }
+ reloadButtonMapping();
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
+}
+
+// SIMpad boardcontrol register CS3
+#define SIMPAD_BOARDCONTROL "/proc/cs3"
+#define SIMPAD_VCC_5V_EN 0x0001 // For 5V PCMCIA
+#define SIMPAD_VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA
+#define SIMPAD_EN1 0x0004 // This is only for EPROM's
+#define SIMPAD_EN0 0x0008 // Both should be enable for 3.3V or 5V
+#define SIMPAD_DISPLAY_ON 0x0010
+#define SIMPAD_PCMCIA_BUFF_DIS 0x0020
+#define SIMPAD_MQ_RESET 0x0040
+#define SIMPAD_PCMCIA_RESET 0x0080
+#define SIMPAD_DECT_POWER_ON 0x0100
+#define SIMPAD_IRDA_SD 0x0200 // Shutdown for powersave
+#define SIMPAD_RS232_ON 0x0400
+#define SIMPAD_SD_MEDIAQ 0x0800 // Shutdown for powersave
+#define SIMPAD_LED2_ON 0x1000
+#define SIMPAD_IRDA_MODE 0x2000 // Fast/Slow IrDA mode
+#define SIMPAD_ENABLE_5V 0x4000 // Enable 5V circuit
+#define SIMPAD_RESET_SIMCARD 0x8000
+
+//SIMpad touchscreen backlight strength control
+#define SIMPAD_BACKLIGHT_CONTROL "/proc/driver/mq200/registers/PWM_CONTROL"
+#define SIMPAD_BACKLIGHT_MASK 0x00a10044
+
+QValueList <OLed> SIMpad::ledList() const
+{
+ QValueList <OLed> vl;
+ vl << Led_Power; //FIXME which LED is LED2 ? The green one or the amber one?
+ //vl << Led_Mail; //TODO find out if LED1 is accessible anyway
+ return vl;
+}
+
+QValueList <OLedState> SIMpad::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Power ) //FIXME which LED is LED2 ? The green one or the amber one?
+ vl << Led_Off << Led_On;
+ //else if ( l == Led_Mail ) //TODO find out if LED1 is accessible anyway
+ //vl << Led_Off;
+ return vl;
+}
+
+OLedState SIMpad::ledState ( OLed l ) const
+{
+ switch ( l ) {
+ case Led_Power:
+ return m_leds [0];
+ //case Led_Mail:
+ // return m_leds [1];
+ default:
+ return Led_Off;
+ }
+}
+
+bool SIMpad::setLedState ( OLed l, OLedState st )
+{
+#if 0
+ static int fd = ::open ( SIMPAD_BOARDCONTROL, O_RDWR | O_NONBLOCK );
+
+ /*TODO Implement this like that:
+ read from cs3
+ && with SIMPAD_LED2_ON
+ write to cs3 */
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+
+#endif
+ return false;
+}
+
+
+bool SIMpad::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
+{
+ //TODO
+ return false;
+}
+
+void SIMpad::timerEvent ( QTimerEvent * )
+{
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
+}
+
+
+void SIMpad::alarmSound()
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play();
+ while ( !snd. isFinished())
+ qApp->processEvents();
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+#endif
+}
+
+
+bool SIMpad::suspend() // Must override because SIMpad does NOT have apm
+{
+ qDebug( "ODevice for SIMpad: suspend()" );
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs, tvn;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync(); // flush fs caches
+ res = ( ::system ( "cat /dev/fb/0 >/tmp/.buffer; echo > /proc/sys/pm/suspend; cat /tmp/.buffer >/dev/fb/0" ) == 0 ); //TODO make better :)
+
+ return res;
+}
+
+
+bool SIMpad::setSoftSuspend ( bool soft )
+{
+ qDebug( "ODevice for SIMpad: UNHANDLED setSoftSuspend(%s)", soft? "on" : "off" );
+ return false;
+}
+
+
+bool SIMpad::setDisplayStatus ( bool on )
+{
+ qDebug( "ODevice for SIMpad: setDisplayStatus(%s)", on? "on" : "off" );
+
+ bool res = false;
+ int fd;
+
+ QString cmdline = QString().sprintf( "echo %s > /proc/cs3", on ? "0xd41a" : "0xd40a" ); //TODO make better :)
+
+ res = ( ::system( (const char*) cmdline ) == 0 );
+
+ return res;
+}
+
+
+bool SIMpad::setDisplayBrightness ( int bright )
+{
+ qDebug( "ODevice for SIMpad: setDisplayBrightness( %d )", bright );
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 1 )
+ bright = 0;
+
+ if (( fd = ::open ( SIMPAD_BACKLIGHT_CONTROL, O_WRONLY )) >= 0 ) {
+ int value = 255 - bright;
+ const int mask = SIMPAD_BACKLIGHT_MASK;
+ value = value << 8;
+ value += mask;
+ char writeCommand[100];
+ const int count = sprintf( writeCommand, "0x%x\n", value );
+ res = ( ::write ( fd, writeCommand, count ) != -1 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+
+int SIMpad::displayBrightnessResolution() const
+{
+ return 255; // All SIMpad models share the same display
+}
+
diff --git a/libopie2/opiecore/device/odevice_yopy.cpp b/libopie2/opiecore/device/odevice_yopy.cpp
new file mode 100644
index 0000000..9d0cdeb
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_yopy.cpp
@@ -0,0 +1,212 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class Yopy : public ODevice
+{
+ protected:
+
+ virtual void init();
+ virtual void initButtons();
+
+ public:
+ virtual bool suspend();
+
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution() const;
+
+ static bool isYopy();
+};
+
+struct yopy_button {
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} yopy_buttons [] = {
+{ Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Action Button"),
+ "devicebuttons/yopy_action",
+ "datebook", "nextView()",
+ "today", "raise()" },
+{ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "OK Button"),
+ "devicebuttons/yopy_ok",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+{ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "End Button"),
+ "devicebuttons/yopy_end",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+};
+
+bool Yopy::isYopy()
+{
+QFile f( "/proc/cpuinfo" );
+if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine() ) {
+ if ( line. left ( 8 ) == "Hardware" ) {
+ int loc = line. find ( ":" );
+ if ( loc != -1 ) {
+ QString model =
+ line. mid ( loc + 2 ). simplifyWhiteSpace( );
+ return ( model == "Yopy" );
+ }
+ }
+ }
+}
+return false;
+}
+
+void Yopy::init()
+{
+d->m_vendorstr = "G.Mate";
+d->m_vendor = Vendor_GMate;
+d->m_modelstr = "Yopy3700";
+d->m_model = Model_Yopy_3700;
+d->m_rotation = Rot0;
+
+d->m_systemstr = "Linupy";
+d->m_system = System_Linupy;
+
+QFile f ( "/etc/issue" );
+if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+ ts.readLine();
+ d->m_sysverstr = ts. readLine();
+ f. close();
+}
+}
+
+void Yopy::initButtons()
+{
+if ( d->m_buttons )
+ return;
+
+d->m_buttons = new QValueList <ODeviceButton>;
+
+for (uint i = 0; i < ( sizeof( yopy_buttons ) / sizeof(yopy_button)); i++) {
+
+ yopy_button *ib = yopy_buttons + i;
+
+ ODeviceButton b;
+
+ b. setKeycode ( ib->code );
+ b. setUserText ( QObject::tr ( "Button", ib->utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib->pix ));
+ b. setFactoryPresetPressedAction
+ (OQCopMessage(makeChannel(ib->fpressedservice), ib->fpressedaction));
+ b. setFactoryPresetHeldAction
+ (OQCopMessage(makeChannel(ib->fheldservice), ib->fheldaction));
+
+ d->m_buttons->append ( b );
+}
+reloadButtonMapping();
+
+QCopChannel *sysch = new QCopChannel("QPE/System", this);
+connect(sysch, SIGNAL(received(const QCString &, const QByteArray & )),
+ this, SLOT(systemMessage(const QCString &, const QByteArray & )));
+}
+
+bool Yopy::suspend()
+{
+/* Opie for Yopy does not implement its own power management at the
+ moment. The public version runs parallel to X, and relies on the
+ existing power management features. */
+return false;
+}
+
+bool Yopy::setDisplayBrightness(int bright)
+{
+/* The code here works, but is disabled as the current version runs
+ parallel to X, and relies on the existing backlight demon. */
+#if 0
+if ( QFile::exists("/proc/sys/pm/light") ) {
+ int fd = ::open("/proc/sys/pm/light", O_WRONLY);
+ if (fd >= 0 ) {
+ if (bright)
+ ::write(fd, "1\n", 2);
+ else
+ ::write(fd, "0\n", 2);
+ ::close(fd);
+ return true;
+ }
+}
+#endif
+return false;
+}
+
+int Yopy::displayBrightnessResolution() const
+{
+ return 2;
+}
+
diff --git a/libopie2/opiecore/device/odevice_zaurus.cpp b/libopie2/opiecore/device/odevice_zaurus.cpp
new file mode 100644
index 0000000..a6e8b82
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_zaurus.cpp
@@ -0,0 +1,790 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "odevice.h"
+
+/* QT */
+#include <qapplication.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwindowsystem_qws.h>
+
+/* OPIE */
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+
+/* STD */
+#include <fcntl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class Zaurus : public ODevice
+{
+
+ protected:
+ virtual void init();
+ virtual void initButtons();
+
+ public:
+ virtual bool setSoftSuspend ( bool soft );
+
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution() const;
+
+ virtual void alarmSound();
+ virtual void keySound();
+ virtual void touchSound();
+
+ virtual QValueList <OLed> ledList() const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState( OLed led ) const;
+ virtual bool setLedState( OLed led, OLedState st );
+
+ virtual bool hasHingeSensor() const;
+ virtual OHingeStatus readHingeSensor();
+
+ static bool isZaurus();
+
+ virtual bool suspend();
+ virtual Transformation rotation() const;
+ virtual ODirection direction() const;
+
+ protected:
+ virtual void buzzer ( int snd );
+
+ OLedState m_leds [1];
+ bool m_embedix;
+};
+
+struct z_button {
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} z_buttons [] = {
+ { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/z_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/z_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/z_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/z_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
+ "devicebuttons/z_mail",
+ "mail", "raise()",
+ "mail", "newMail()" },
+};
+
+struct z_button z_buttons_c700 [] = {
+ { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/z_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/z_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/z_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/z_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Qt::Key_F14, QT_TRANSLATE_NOOP("Button", "Display Rotate"),
+ "devicebuttons/z_hinge",
+ "QPE/Rotation", "rotateDefault()",
+ "QPE/Dummy", "doNothing()" },
+};
+
+// Check whether this device is the sharp zaurus..
+// FIXME This gets unnecessary complicated. We should think about splitting the Zaurus
+// class up into individual classes. We need three classes
+//
+// Zaurus-Collie (SA-model w/ 320x240 lcd, for SL5500 and SL5000)
+// Zaurus-Poodle (PXA-model w/ 320x240 lcd, for SL5600)
+// Zaurus-Corgi (PXA-model w/ 640x480 lcd, for C700, C750, C760, and C860)
+//
+// Only question right now is: Do we really need to do it? Because as soon
+// as the OpenZaurus kernel is ready, there will be a unified interface for all
+// Zaurus models (concerning apm, backlight, buttons, etc.)
+//
+// Comments? - mickeyl.
+
+bool Zaurus::isZaurus()
+{
+
+ // If the special devices by embedix exist, it is quite simple: it is a Zaurus !
+ if ( QFile::exists ( "/dev/sharp_buz" ) || QFile::exists ( "/dev/sharp_led" ) ){
+ return true;
+ }
+
+ // On non-embedix kernels, we have to look closer.
+ bool is_zaurus = false;
+ QFile f ( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QString model;
+ QFile f ( "/proc/cpuinfo" );
+
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine() ) {
+ if ( line. left ( 8 ) == "Hardware" )
+ break;
+ }
+ int loc = line. find ( ":" );
+ if ( loc != -1 )
+ model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
+
+ if ( model == "Sharp-Collie"
+ || model == "Collie"
+ || model == "SHARP Corgi"
+ || model == "SHARP Shepherd"
+ || model == "SHARP Poodle"
+ || model == "SHARP Husky"
+ )
+ is_zaurus = true;
+
+ }
+ return is_zaurus;
+}
+
+
+void Zaurus::init()
+{
+ d->m_vendorstr = "Sharp";
+ d->m_vendor = Vendor_Sharp;
+ m_embedix = true; // Not openzaurus means: It has an embedix kernel !
+
+ // QFile f ( "/proc/filesystems" );
+ QString model;
+
+ // It isn't a good idea to check the system configuration to
+ // detect the distribution !
+ // Otherwise it may happen that any other distribution is detected as openzaurus, just
+ // because it uses a jffs2 filesystem..
+ // (eilers)
+ // if ( f. open ( IO_ReadOnly ) && ( QTextStream ( &f ). read(). find ( "\tjffs2\n" ) >= 0 )) {
+ QFile f ("/etc/oz_version");
+ if ( f.exists() ){
+ d->m_vendorstr = "OpenZaurus Team";
+ d->m_systemstr = "OpenZaurus";
+ d->m_system = System_OpenZaurus;
+
+ if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+ d->m_sysverstr = ts. readLine();//. mid ( 10 );
+ f. close();
+ }
+
+ // Openzaurus sometimes uses the embedix kernel!
+ // => Check whether this is an embedix kernel
+ FILE *uname = popen("uname -r", "r");
+ QString line;
+ if ( f.open(IO_ReadOnly, uname) ) {
+ QTextStream ts ( &f );
+ line = ts. readLine();
+ int loc = line. find ( "embedix" );
+ if ( loc != -1 )
+ m_embedix = true;
+ else
+ m_embedix = false;
+ f. close();
+ }
+ pclose(uname);
+ }
+ else {
+ d->m_systemstr = "Zaurus";
+ d->m_system = System_Zaurus;
+ }
+
+ f. setName ( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine() ) {
+ if ( line. left ( 8 ) == "Hardware" )
+ break;
+ }
+ int loc = line. find ( ":" );
+ if ( loc != -1 )
+ model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
+ }
+
+ if ( model == "SHARP Corgi" ) {
+ d->m_model = Model_Zaurus_SLC7x0;
+ d->m_modelstr = "Zaurus SL-C700";
+ } else if ( model == "SHARP Shepherd" ) {
+ d->m_model = Model_Zaurus_SLC7x0;
+ d->m_modelstr = "Zaurus SL-C750";
+ } else if ( model == "SHARP Husky" ) {
+ d->m_model = Model_Zaurus_SLC7x0;
+ d->m_modelstr = "Zaurus SL-C760";
+ } else if ( model == "SHARP Poodle" ) {
+ d->m_model = Model_Zaurus_SLB600;
+ d->m_modelstr = "Zaurus SL-B500 or SL-5600";
+ } else if ( model == "Sharp-Collie" || model == "Collie" ) {
+ d->m_model = Model_Zaurus_SL5500;
+ d->m_modelstr = "Zaurus SL-5500 or SL-5000d";
+ } else {
+ d->m_model = Model_Zaurus_SL5500;
+ d->m_modelstr = "Zaurus (Model unknown)";
+ }
+
+ bool flipstate = false;
+ switch ( d->m_model ) {
+ case Model_Zaurus_SLA300:
+ d->m_rotation = Rot0;
+ break;
+ case Model_Zaurus_SLC7x0:
+ d->m_rotation = rotation();
+ d->m_direction = direction();
+ break;
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ d->m_rotation = Rot270;
+ break;
+ }
+ m_leds [0] = Led_Off;
+}
+
+void Zaurus::initButtons()
+{
+ if ( d->m_buttons )
+ return;
+
+ d->m_buttons = new QValueList <ODeviceButton>;
+
+ struct z_button * pz_buttons;
+ int buttoncount;
+ switch ( d->m_model ) {
+ case Model_Zaurus_SLC7x0:
+ pz_buttons = z_buttons_c700;
+ buttoncount = ARRAY_SIZE(z_buttons_c700);
+ break;
+ default:
+ pz_buttons = z_buttons;
+ buttoncount = ARRAY_SIZE(z_buttons);
+ break;
+ }
+
+ for ( int i = 0; i < buttoncount; i++ ) {
+ struct z_button *zb = pz_buttons + i;
+ ODeviceButton b;
+
+ b. setKeycode ( zb->code );
+ b. setUserText ( QObject::tr ( "Button", zb->utext ));
+ b. setPixmap ( Resource::loadPixmap ( zb->pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( zb->fpressedservice ),
+ zb->fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( zb->fheldservice ),
+ zb->fheldaction ));
+
+ d->m_buttons->append ( b );
+ }
+
+ reloadButtonMapping();
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )),
+ this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
+}
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+//#include <asm/sharp_char.h> // including kernel headers is evil ...
+
+#define SHARP_DEV_IOCTL_COMMAND_START 0x5680
+
+#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
+
+#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
+#define SHARP_BUZ_KEYSOUND 2 /* key sound */
+#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
+
+/* --- for SHARP_BUZZER device --- */
+
+//#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+//#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
+
+#define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1)
+#define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2)
+#define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3)
+#define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4)
+#define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5)
+
+//#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
+//#define SHARP_BUZ_KEYSOUND 2 /* key sound */
+
+//#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */
+//#define SHARP_PDA_WARNSOUND 4 /* warning occurred */
+//#define SHARP_PDA_ERRORSOUND 5 /* error occurred */
+//#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */
+//#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */
+//#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */
+//#define SHARP_PDA_APPSTART 9 /* application start */
+//#define SHARP_PDA_APPQUIT 10 /* application ends */
+
+//#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
+//#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */
+//#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */
+//#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */
+//
+
+#define SHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+#define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1)
+
+#define SHARP_IOCTL_GET_ROTATION 0x413c
+
+typedef struct sharp_led_status {
+int which; /* select which LED status is wanted. */
+int status; /* set new led status if you call SHARP_LED_SETSTATUS */
+} sharp_led_status;
+
+#define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */
+
+#define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */
+#define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */
+#define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */
+
+// #include <asm/sharp_apm.h> // including kernel headers is evil ...
+
+#define APM_IOCGEVTSRC OD_IOR( 'A', 203, int )
+#define APM_IOCSEVTSRC OD_IORW( 'A', 204, int )
+#define APM_EVT_POWER_BUTTON (1 << 0)
+
+#define FL_IOCTL_STEP_CONTRAST 100
+
+
+void Zaurus::buzzer ( int sound )
+{
+#ifndef QT_NO_SOUND
+ QString soundname;
+
+ // Not all devices have real sound
+ if ( d->m_model == Model_Zaurus_SLC7x0
+ || d->m_model == Model_Zaurus_SLB600 ){
+
+ switch ( sound ){
+ case SHARP_BUZ_SCHEDULE_ALARM:
+ soundname = "alarm";
+ break;
+ case SHARP_BUZ_TOUCHSOUND:
+ soundname = "touchsound";
+ break;
+ case SHARP_BUZ_KEYSOUND:
+ soundname = "keysound";
+ break;
+ default:
+ soundname = "alarm";
+
+ }
+ }
+
+ // If a soundname is defined, we expect that this device has
+ // sound capabilities.. Otherwise we expect to have the buzzer
+ // device..
+ if ( !soundname.isEmpty() ){
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ Sound snd ( soundname );
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play();
+ while ( !snd. isFinished())
+ qApp->processEvents();
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+ } else {
+ int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK );
+
+ if ( fd >= 0 ) {
+ ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound );
+ ::close ( fd );
+ }
+
+ }
+#endif
+}
+
+
+void Zaurus::alarmSound()
+{
+ buzzer ( SHARP_BUZ_SCHEDULE_ALARM );
+}
+
+void Zaurus::touchSound()
+{
+ buzzer ( SHARP_BUZ_TOUCHSOUND );
+}
+
+void Zaurus::keySound()
+{
+ buzzer ( SHARP_BUZ_KEYSOUND );
+}
+
+
+QValueList <OLed> Zaurus::ledList() const
+{
+ QValueList <OLed> vl;
+ vl << Led_Mail;
+ return vl;
+}
+
+QValueList <OLedState> Zaurus::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Mail )
+ vl << Led_Off << Led_On << Led_BlinkSlow;
+ return vl;
+}
+
+OLedState Zaurus::ledState ( OLed which ) const
+{
+ if ( which == Led_Mail )
+ return m_leds [0];
+ else
+ return Led_Off;
+}
+
+bool Zaurus::setLedState ( OLed which, OLedState st )
+{
+ if (!m_embedix) // Currently not supported on non_embedix kernels
+ return false;
+
+ static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK );
+
+ if ( which == Led_Mail ) {
+ if ( fd >= 0 ) {
+ struct sharp_led_status leds;
+ ::memset ( &leds, 0, sizeof( leds ));
+ leds. which = SHARP_LED_MAIL_EXISTS;
+ bool ok = true;
+
+ switch ( st ) {
+ case Led_Off : leds. status = LED_MAIL_NO_UNREAD_MAIL; break;
+ case Led_On : leds. status = LED_MAIL_NEWMAIL_EXISTS; break;
+ case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break;
+ default : ok = false;
+ }
+
+ if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) {
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Zaurus::setSoftSuspend ( bool soft )
+{
+ if (!m_embedix) {
+ /* non-Embedix kernels dont have kernel autosuspend */
+ return ODevice::setSoftSuspend( soft );
+ }
+
+ bool res = false;
+ int fd;
+
+ if ((( fd = ::open ( "/dev/apm_bios", O_RDWR )) >= 0 ) ||
+ (( fd = ::open ( "/dev/misc/apm_bios",O_RDWR )) >= 0 )) {
+
+ int sources = ::ioctl ( fd, APM_IOCGEVTSRC, 0 ); // get current event sources
+
+ if ( sources >= 0 ) {
+ if ( soft )
+ sources &= ~APM_EVT_POWER_BUTTON;
+ else
+ sources |= APM_EVT_POWER_BUTTON;
+
+ if ( ::ioctl ( fd, APM_IOCSEVTSRC, sources ) >= 0 ) // set new event sources
+ res = true;
+ else
+ perror ( "APM_IOCGEVTSRC" );
+ }
+ else
+ perror ( "APM_IOCGEVTSRC" );
+
+ ::close ( fd );
+ }
+ else
+ perror ( "/dev/apm_bios or /dev/misc/apm_bios" );
+
+ return res;
+}
+
+
+bool Zaurus::setDisplayBrightness ( int bright )
+{
+ //qDebug( "Zaurus::setDisplayBrightness( %d )", bright );
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 ) bright = 255;
+ if ( bright < 0 ) bright = 0;
+
+ if ( m_embedix )
+ {
+ if ( d->m_model == Model_Zaurus_SLC7x0 )
+ {
+ //qDebug( "using special treatment for devices with the corgi backlight interface" );
+ // special treatment for devices with the corgi backlight interface
+ if (( fd = ::open ( "/proc/driver/fl/corgi-bl", O_WRONLY )) >= 0 )
+ {
+ int value = ( bright == 1 ) ? 1 : bright * ( 17.0 / 255.0 );
+ char writeCommand[100];
+ const int count = sprintf( writeCommand, "0x%x\n", value );
+ res = ( ::write ( fd, writeCommand, count ) != -1 );
+ ::close ( fd );
+ }
+ return res;
+ }
+ else
+ {
+ // standard treatment for devices with the dumb embedix frontlight interface
+ if (( fd = ::open ( "/dev/fl", O_WRONLY )) >= 0 ) {
+ int bl = ( bright * 4 + 127 ) / 255; // only 4 steps on zaurus
+ if ( bright && !bl )
+ bl = 1;
+ res = ( ::ioctl ( fd, FL_IOCTL_STEP_CONTRAST, bl ) == 0 );
+ ::close ( fd );
+ }
+ }
+ }
+ else
+ {
+ // special treatment for the OpenZaurus unified interface
+ #define FB_BACKLIGHT_SET_BRIGHTNESS _IOW('F', 1, u_int) /* set brightness */
+ if (( fd = ::open ( "/dev/fb0", O_WRONLY )) >= 0 ) {
+ res = ( ::ioctl ( fd , FB_BACKLIGHT_SET_BRIGHTNESS, bright ) == 0 );
+ ::close ( fd );
+ }
+ }
+ return res;
+}
+
+bool Zaurus::suspend()
+{
+ qDebug("ODevice::suspend");
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ if ( d->m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs, tvn;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync(); // flush fs caches
+ res = ( ::system ( "apm --suspend" ) == 0 );
+
+ // This is needed because the iPAQ apm implementation is asynchronous and we
+ // can not be sure when exactly the device is really suspended
+ // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
+
+ if ( res ) {
+ do { // Yes, wait 15 seconds. This APM bug sucks big time.
+ ::usleep ( 200 * 1000 );
+ ::gettimeofday ( &tvn, 0 );
+ } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 15000 );
+ }
+
+ QCopEnvelope ( "QPE/Rotation", "rotateDefault()" );
+ return res;
+}
+
+
+Transformation Zaurus::rotation() const
+{
+ Transformation rot;
+ int handle = 0;
+ int retval = 0;
+
+ switch ( d->m_model ) {
+ case Model_Zaurus_SLC7x0:
+ handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1) {
+ return Rot270;
+ } else {
+ retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+
+ if (retval == 2 )
+ rot = Rot0;
+ else
+ rot = Rot270;
+ }
+ break;
+ case Model_Zaurus_SLA300:
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ rot = d->m_rotation;
+ break;
+ }
+
+ return rot;
+}
+ODirection Zaurus::direction() const
+{
+ ODirection dir;
+ int handle = 0;
+ int retval = 0;
+ switch ( d->m_model ) {
+ case Model_Zaurus_SLC7x0:
+ handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1) {
+ dir = CW;
+ } else {
+ retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+ if (retval == 2 )
+ dir = CCW;
+ else
+ dir = CW;
+ }
+ break;
+ case Model_Zaurus_SLA300:
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ dir = d->m_direction;
+ break;
+ }
+ return dir;
+
+}
+
+int Zaurus::displayBrightnessResolution() const
+{
+ if (m_embedix)
+ return d->m_model == Model_Zaurus_SLC7x0 ? 18 : 5;
+ else
+ return 256;
+}
+
+bool Zaurus::hasHingeSensor() const
+{
+ return d->m_model == Model_Zaurus_SLC7x0;
+}
+
+OHingeStatus Zaurus::readHingeSensor()
+{
+ int handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1)
+ {
+ qWarning("Zaurus::readHingeSensor() - failed (%s)", "unknown reason" ); //FIXME: use strerror
+ return CASE_UNKNOWN;
+ }
+ else
+ {
+ int retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+ if ( retval == CASE_CLOSED || retval == CASE_PORTRAIT || retval == CASE_LANDSCAPE )
+ {
+ qDebug( "Zaurus::readHingeSensor() - result = %d", retval );
+ return static_cast<OHingeStatus>( retval );
+ }
+ else
+ {
+ qWarning("Zaurus::readHingeSensor() - couldn't compute hinge status!" );
+ return CASE_UNKNOWN;
+ }
+ }
+}
diff --git a/libopie2/opiecore/device/odevicebutton.cpp b/libopie2/opiecore/device/odevicebutton.cpp
new file mode 100644
index 0000000..0b593d5
--- a/dev/null
+++ b/libopie2/opiecore/device/odevicebutton.cpp
@@ -0,0 +1,246 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) The Opie Team <opie-devel@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. 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
+..}^=.=       =       ; 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <qpixmap.h>
+#include <qstring.h>
+
+#include <qpe/qcopenvelope_qws.h>
+#include <opie2/odevicebutton.h>
+
+using namespace Opie;
+
+class OQCopMessageData
+{
+ public:
+ QCString m_channel;
+ QCString m_message;
+ QByteArray m_data;
+};
+
+
+OQCopMessage::OQCopMessage()
+ : d ( 0 )
+{
+ init ( QCString(), QCString(), QByteArray());
+}
+
+OQCopMessage::OQCopMessage ( const OQCopMessage &copy )
+ : d ( 0 )
+{
+ init ( copy. channel(), copy. message(), copy. data());
+}
+
+OQCopMessage &OQCopMessage::operator = ( const OQCopMessage &assign )
+{
+ init ( assign. channel(), assign. message(), assign. data());
+ return *this;
+}
+
+OQCopMessage::OQCopMessage ( const QCString &ch, const QCString &m, const QByteArray &arg )
+ : d ( 0 )
+{
+ init ( ch, m, arg );
+}
+
+void OQCopMessage::init ( const QCString &ch, const QCString &m, const QByteArray &arg )
+{
+ if ( !d )
+ d = new OQCopMessageData();
+ d->m_channel = ch;
+ d->m_message = m;
+ d->m_data = arg;
+}
+
+bool OQCopMessage::send()
+{
+ if ( d->m_channel. isEmpty() || d->m_message. isEmpty() )
+ return false;
+
+ QCopEnvelope e ( d->m_channel, d->m_message );
+
+ if ( d->m_data. size())
+ e. writeRawBytes ( d->m_data. data(), d->m_data. size());
+
+ return true;
+}
+
+QCString OQCopMessage::channel() const
+{
+ return d->m_channel;
+}
+
+QCString OQCopMessage::message() const
+{
+ return d->m_message;
+}
+
+QByteArray OQCopMessage::data() const
+{
+ return d->m_data;
+}
+
+bool OQCopMessage::isNull() const
+{
+ return d->m_message.isNull() || d->m_channel.isNull();
+}
+void OQCopMessage::setChannel ( const QCString &ch )
+{
+ d->m_channel = ch;
+}
+
+void OQCopMessage::setMessage ( const QCString &m )
+{
+ d->m_message = m;
+}
+
+void OQCopMessage::setData ( const QByteArray &data )
+{
+ d->m_data = data;
+}
+
+/*! \class Opie::ODeviceButton
+ \brief The Opie::ODeviceButton class represents a physical user mappable button on a Qtopia device.
+
+ This class represents a physical button on a Qtopia device. A
+ device may have "user programmable" buttons.
+ The location and number of buttons will vary from device to
+ device. userText() and pixmap() may be used to describe this button
+ to the user in help documentation.
+
+ \ingroup qtopiaemb
+ \internal
+*/
+
+ODeviceButton::ODeviceButton()
+{}
+
+ODeviceButton::~ODeviceButton()
+{}
+
+/*!
+Returns the button's keycode.
+*/
+ushort ODeviceButton::keycode() const
+{
+ return m_Keycode;
+}
+
+
+/*!
+This function returns a human readable, translated description of the button.
+*/
+QString ODeviceButton::userText() const
+{
+ return m_UserText;
+}
+
+/*!
+This function returns the pixmap for this button. If there isn't one
+it will return an empty (null) pixmap.
+*/
+QPixmap ODeviceButton::pixmap() const
+{
+ return m_Pixmap;
+}
+
+/*!
+This function returns the factory preset (default) action for when this button
+is pressed. The return value is a legal QCop message.
+*/
+OQCopMessage ODeviceButton::factoryPresetPressedAction() const
+{
+ return m_FactoryPresetPressedAction;
+}
+
+/*!
+This function returns the user assigned action for when this button is pressed.
+If no action is assigned, factoryPresetAction() is returned.
+*/
+OQCopMessage ODeviceButton::pressedAction() const
+{
+ if (m_PressedAction.channel().isEmpty())
+ return factoryPresetPressedAction();
+ return m_PressedAction;
+}
+
+/*!
+This function returns the factory preset (default) action for when this button
+is pressed and held. The return value is a legal QCop message.
+*/
+OQCopMessage ODeviceButton::factoryPresetHeldAction() const
+{
+ return m_FactoryPresetHeldAction;
+}
+
+/*!
+This function returns the user assigned action for when this button is pressed
+and held. If no action is assigned, factoryPresetAction() is returned.
+*/
+OQCopMessage ODeviceButton::heldAction() const
+{
+ if (m_HeldAction.channel().isEmpty())
+ return factoryPresetHeldAction();
+ return m_HeldAction;
+}
+
+void ODeviceButton::setKeycode(ushort keycode)
+{
+ m_Keycode = keycode;
+}
+
+void ODeviceButton::setUserText(const QString& text)
+{
+ m_UserText = text;
+}
+
+void ODeviceButton::setPixmap(const QPixmap& picture)
+{
+ m_Pixmap = picture;
+}
+
+void ODeviceButton::setFactoryPresetPressedAction(const OQCopMessage& action)
+{
+ m_FactoryPresetPressedAction = action;
+}
+
+
+void ODeviceButton::setPressedAction(const OQCopMessage& action)
+{
+ m_PressedAction = action;
+}
+
+void ODeviceButton::setFactoryPresetHeldAction(const OQCopMessage& action)
+{
+ m_FactoryPresetHeldAction = action;
+}
+
+void ODeviceButton::setHeldAction(const OQCopMessage& action)
+{
+ m_HeldAction = action;
+}
diff --git a/libopie2/opiecore/device/odevicebutton.h b/libopie2/opiecore/device/odevicebutton.h
new file mode 100644
index 0000000..a66b88f
--- a/dev/null
+++ b/libopie2/opiecore/device/odevicebutton.h
@@ -0,0 +1,108 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef DEVICE_BUTTON_H
+#define DEVICE_BUTTON_H
+
+#include <qpixmap.h>
+#include <qstring.h>
+
+class OQCopMessageData;
+
+namespace Opie
+{
+
+class OQCopMessage
+{
+public:
+ OQCopMessage ( );
+ OQCopMessage ( const OQCopMessage &copy );
+ OQCopMessage ( const QCString &m_channel, const QCString &message, const QByteArray &args = QByteArray ( ));
+
+ OQCopMessage &operator = ( const OQCopMessage &assign );
+
+ void setChannel ( const QCString &channel );
+ void setMessage ( const QCString &message );
+ void setData ( const QByteArray &ba );
+
+ QCString channel ( ) const;
+ QCString message ( ) const;
+ QByteArray data ( ) const;
+
+ bool isNull()const;
+
+ bool send ( );
+
+private:
+ void init ( const QCString &m_channel, const QCString &message, const QByteArray &args );
+
+ OQCopMessageData *d;
+ class Private;
+ Private* m_data;
+};
+
+
+/**
+ * This class represents a physical button on a Qtopia device. A device may
+ * have n "user programmable" buttons, which are number 1..n. The location
+ * and number of buttons will vary from device to device. userText() and pixmap()
+ * may be used to describe this button to the user in help documentation.
+ *
+ * @version 1.0
+ * @author Trolltech
+ * @short A representation of buttons
+ */
+
+class ODeviceButton
+{
+ public:
+ ODeviceButton();
+ virtual ~ODeviceButton();
+
+ ushort keycode ( ) const;
+ QString userText ( ) const;
+ QPixmap pixmap ( ) const;
+ OQCopMessage factoryPresetPressedAction ( ) const;
+ OQCopMessage pressedAction ( ) const;
+ OQCopMessage factoryPresetHeldAction ( ) const;
+ OQCopMessage heldAction ( ) const;
+
+ void setKeycode ( ushort keycode );
+ void setUserText ( const QString& text );
+ void setPixmap ( const QPixmap& picture );
+ void setFactoryPresetPressedAction ( const OQCopMessage& qcopMessage );
+ void setPressedAction ( const OQCopMessage& qcopMessage );
+ void setFactoryPresetHeldAction ( const OQCopMessage& qcopMessage );
+ void setHeldAction ( const OQCopMessage& qcopMessage );
+
+ private:
+ ushort m_Keycode;
+ QString m_UserText;
+ QPixmap m_Pixmap;
+ OQCopMessage m_FactoryPresetPressedAction;
+ OQCopMessage m_PressedAction;
+ OQCopMessage m_FactoryPresetHeldAction;
+ OQCopMessage m_HeldAction;
+ class Private;
+ Private *d;
+};
+
+}
+
+#endif
diff --git a/libopie2/opiecore/libopiecore2.control b/libopie2/opiecore/libopiecore2.control
index 956d24f..f0a3afc 100644
--- a/libopie2/opiecore/libopiecore2.control
+++ b/libopie2/opiecore/libopiecore2.control
@@ -1,11 +1,11 @@
Package: libopiecore2
Files: $OPIEDIR/lib/libopiecore2.so.*
Priority: optional
Section: opie/system
Maintainer: Opie Team <opie@handhelds.org>
Architecture: arm
-Version: 1.8.2-$SUB_VERSION.2
+Version: 1.8.3-$SUB_VERSION.2
Depends: libqpe1
Provides: libopiecore2
Description: Opie library 2.0 CORE
diff --git a/libopie2/opiecore/opiecore.pro b/libopie2/opiecore/opiecore.pro
index 237a5ed..97e8146 100644
--- a/libopie2/opiecore/opiecore.pro
+++ b/libopie2/opiecore/opiecore.pro
@@ -1,35 +1,49 @@
TEMPLATE = lib
CONFIG += qt warn_on debug
DESTDIR = $(OPIEDIR)/lib
HEADERS = oapplication.h \
oconfig.h \
odebug.h \
+ odevice.h \
+ odevicebutton.h \
oglobal.h \
oglobalsettings.h \
+ oprocess.h \
+ oprocctrl.h \
ostorageinfo.h
SOURCES = oapplication.cpp \
oconfig.cpp \
odebug.cpp \
+ odevice.cpp \
+ odevicebutton.cpp \
+ odevice_ipaq.cpp \
+ odevice_jornada.cpp \
+ odevice_ramses.cpp \
+ odevice_simpad.cpp \
+ odevice_zaurus.cpp \
+ odevice_yopy.cpp \
oglobal.cpp \
oglobalsettings.cpp \
+ oprocess.cpp \
+ oprocctrl.cpp \
ostorageinfo.cpp
INTERFACES =
TARGET = opiecore2
-VERSION = 1.8.2
+VERSION = 1.8.3
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
MOC_DIR = moc
OBJECTS_DIR = obj
!contains( platform, x11 ) {
LIBS = -lqpe
include ( $(OPIEDIR)/include.pro )
}
contains( platform, x11 ) {
LIBS = -L$(OPIEDIR)/lib -Wl,-rpath,$(OPIEDIR)/lib
}
diff --git a/libopie2/opiecore/oprocctrl.cpp b/libopie2/opiecore/oprocctrl.cpp
new file mode 100644
index 0000000..b3d57c8
--- a/dev/null
+++ b/libopie2/opiecore/oprocctrl.cpp
@@ -0,0 +1,284 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan, 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther
+//
+
+//#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <qsocketnotifier.h>
+#include "oprocess.h"
+#include "oprocctrl.h"
+
+OProcessController *OProcessController::theOProcessController = 0;
+
+struct sigaction OProcessController::oldChildHandlerData;
+bool OProcessController::handlerSet = false;
+
+OProcessController::OProcessController()
+{
+ assert( theOProcessController == 0 );
+
+ if (0 > pipe(fd))
+ printf(strerror(errno));
+
+ notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read);
+ notifier->setEnabled(true);
+ QObject::connect(notifier, SIGNAL(activated(int)),
+ this, SLOT(slotDoHousekeeping(int)));
+ connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()),
+ SLOT( delayedChildrenCleanup()));
+
+ theOProcessController = this;
+
+ setupHandlers();
+}
+
+
+void OProcessController::setupHandlers()
+{
+ if( handlerSet )
+ return;
+ struct sigaction act;
+ act.sa_handler=theSigCHLDHandler;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGCHLD);
+ // Make sure we don't block this signal. gdb tends to do that :-(
+ sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
+
+ act.sa_flags = SA_NOCLDSTOP;
+
+ // CC: take care of SunOS which automatically restarts interrupted system
+ // calls (and thus does not have SA_RESTART)
+
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+
+ sigaction( SIGCHLD, &act, &oldChildHandlerData );
+
+ act.sa_handler=SIG_IGN;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_flags = 0;
+ sigaction( SIGPIPE, &act, 0L);
+ handlerSet = true;
+}
+
+void OProcessController::resetHandlers()
+{
+ if( !handlerSet )
+ return;
+ sigaction( SIGCHLD, &oldChildHandlerData, 0 );
+ // there should be no problem with SIGPIPE staying SIG_IGN
+ handlerSet = false;
+}
+
+// block SIGCHLD handler, because it accesses processList
+void OProcessController::addOProcess( OProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.append( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+void OProcessController::removeOProcess( OProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.remove( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+//using a struct which contains both the pid and the status makes it easier to write
+//and read the data into the pipe
+//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received
+//only 4 bytes (with some debug output around the write()'s it received all 8 bytes)
+//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX
+struct waitdata
+{
+ pid_t pid;
+ int status;
+};
+
+void OProcessController::theSigCHLDHandler(int arg)
+{
+ struct waitdata wd;
+ // int status;
+ // pid_t this_pid;
+ int saved_errno;
+
+ saved_errno = errno;
+ // since waitpid and write change errno, we have to save it and restore it
+ // (Richard Stevens, Advanced programming in the Unix Environment)
+
+ bool found = false;
+ if( theOProcessController != 0 )
+ {
+ // iterating the list doesn't perform any system call
+ for( QValueList<OProcess*>::ConstIterator it = theOProcessController->processList.begin();
+ it != theOProcessController->processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning())
+ continue;
+ wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG );
+ if ( wd.pid > 0 )
+ {
+ ::write(theOProcessController->fd[1], &wd, sizeof(wd));
+ found = true;
+ }
+ }
+ }
+ if( !found && oldChildHandlerData.sa_handler != SIG_IGN
+ && oldChildHandlerData.sa_handler != SIG_DFL )
+ oldChildHandlerData.sa_handler( arg ); // call the old handler
+ // handle the rest
+ if( theOProcessController != 0 )
+ {
+ static const struct waitdata dwd = { 0, 0 }
+ ; // delayed waitpid()
+ ::write(theOProcessController->fd[1], &dwd, sizeof(dwd));
+ }
+ else
+ {
+ int dummy;
+ while( waitpid( -1, &dummy, WNOHANG ) > 0 )
+ ;
+ }
+
+ errno = saved_errno;
+}
+
+
+
+void OProcessController::slotDoHousekeeping(int )
+{
+ unsigned int bytes_read = 0;
+ unsigned int errcnt=0;
+ // read pid and status from the pipe.
+ struct waitdata wd;
+ while ((bytes_read < sizeof(wd)) && (errcnt < 50))
+ {
+ int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read);
+ if (r > 0) bytes_read += r;
+ else if (r < 0) errcnt++;
+ }
+ if (errcnt >= 50)
+ {
+ fprintf(stderr,
+ "Error: Max. error count for pipe read "
+ "exceeded in OProcessController::slotDoHousekeeping\n");
+ return; // it makes no sense to continue here!
+ }
+ if (bytes_read != sizeof(wd))
+ {
+ fprintf(stderr,
+ "Error: Could not read info from signal handler %d <> %d!\n",
+ bytes_read, sizeof(wd));
+ return; // it makes no sense to continue here!
+ }
+ if (wd.pid==0)
+ { // special case, see delayedChildrenCleanup()
+ delayedChildrenCleanupTimer.start( 1000, true );
+ return;
+ }
+
+ for( QValueList<OProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it )
+ {
+ OProcess* proc = *it;
+ if (proc->pid() == wd.pid)
+ {
+ // process has exited, so do emit the respective events
+ if (proc->run_mode == OProcess::Block)
+ {
+ // If the reads are done blocking then set the status in proc
+ // but do nothing else because OProcess will perform the other
+ // actions of processHasExited.
+ proc->status = wd.status;
+ proc->runs = false;
+ }
+ else
+ {
+ proc->processHasExited(wd.status);
+ }
+ return;
+ }
+ }
+}
+
+// this is needed e.g. for popen(), which calls waitpid() checking
+// for its forked child, if we did waitpid() directly in the SIGCHLD
+// handler, popen()'s waitpid() call would fail
+void OProcessController::delayedChildrenCleanup()
+{
+ struct waitdata wd;
+ while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 )
+ {
+ for( QValueList<OProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning() || (*it)->pid() != wd.pid )
+ continue;
+ // it's OProcess, handle it
+ ::write(fd[1], &wd, sizeof(wd));
+ break;
+ }
+ }
+}
+
+OProcessController::~OProcessController()
+{
+ assert( theOProcessController == this );
+ resetHandlers();
+
+ notifier->setEnabled(false);
+
+ close(fd[0]);
+ close(fd[1]);
+
+ delete notifier;
+ theOProcessController = 0;
+}
+
+//#include "kprocctrl.moc"
diff --git a/libopie2/opiecore/oprocctrl.h b/libopie2/opiecore/oprocctrl.h
new file mode 100644
index 0000000..44b8a48
--- a/dev/null
+++ b/libopie2/opiecore/oprocctrl.h
@@ -0,0 +1,121 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther
+//
+
+#ifndef __KPROCCTRL_H__
+#define __KPROCCTRL_H__
+
+#include <qvaluelist.h>
+#include <qtimer.h>
+
+#include "oprocess.h"
+
+class OProcessControllerPrivate;
+class QSocketNotifier;
+
+/**
+ * @short Used internally by @ref OProcess
+ * @internal
+ * @author Christian Czezakte <e9025461@student.tuwien.ac.at>
+ *
+ * A class for internal use by OProcess only. -- Exactly one instance
+ * of this class is generated by the first instance of OProcess that is
+ * created (a pointer to it gets stored in @ref theOProcessController ).
+ *
+ * This class takes care of the actual (UN*X) signal handling.
+*/
+class OProcessController : public QObject
+{
+ Q_OBJECT
+
+public:
+ OProcessController();
+ ~OProcessController();
+ //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...)
+
+public:
+
+ /**
+ * Only a single instance of this class is allowed at a time,
+ * and this static variable is used to track the one instance.
+ */
+ static OProcessController *theOProcessController;
+
+ /**
+ * Automatically called upon SIGCHLD.
+ *
+ * Normally you do not need to do anything with this function but
+ * if your application needs to disable SIGCHLD for some time for
+ * reasons beyond your control, you should call this function afterwards
+ * to make sure that no SIGCHLDs where missed.
+ */
+ static void theSigCHLDHandler(int signal);
+ // handler for sigchld
+
+ /**
+ * @internal
+ */
+ static void setupHandlers();
+ /**
+ * @internal
+ */
+ static void resetHandlers();
+ /**
+ * @internal
+ */
+ void addOProcess( OProcess* );
+ /**
+ * @internal
+ */
+ void removeOProcess( OProcess* );
+public slots:
+ /**
+ * @internal
+ */
+ void slotDoHousekeeping(int socket);
+
+private slots:
+ void delayedChildrenCleanup();
+private:
+ int fd[2];
+ QSocketNotifier *notifier;
+ static struct sigaction oldChildHandlerData;
+ static bool handlerSet;
+ QValueList<OProcess*> processList;
+ QTimer delayedChildrenCleanupTimer;
+
+ // Disallow assignment and copy-construction
+ OProcessController( const OProcessController& );
+ OProcessController& operator= ( const OProcessController& );
+
+ OProcessControllerPrivate *d;
+};
+
+
+
+#endif
+
diff --git a/libopie2/opiecore/oprocess.cpp b/libopie2/opiecore/oprocess.cpp
new file mode 100644
index 0000000..fb51bf9
--- a/dev/null
+++ b/libopie2/opiecore/oprocess.cpp
@@ -0,0 +1,970 @@
+/*
+
+ $Id$
+
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+//
+// Changes:
+//
+// March 2nd, 1998: Changed parameter list for KShellProcess:
+// Arguments are now placed in a single string so that
+// <shell> -c <commandstring> is passed to the shell
+// to make the use of "operator<<" consistent with KProcess
+//
+//
+// Ported by Holger Freyther
+// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
+
+
+
+#include "oprocess.h"
+#define _MAY_INCLUDE_KPROCESSCONTROLLER_
+#include "oprocctrl.h"
+
+//#include <config.h>
+
+#include <qfile.h>
+#include <qsocketnotifier.h>
+#include <qregexp.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_INITGROUPS
+#include <grp.h>
+#endif
+#include <pwd.h>
+
+#include <qapplication.h>
+#include <qmap.h>
+//#include <kdebug.h>
+
+/////////////////////////////
+// public member functions //
+/////////////////////////////
+
+class OProcessPrivate
+{
+public:
+ OProcessPrivate() : useShell(false) { }
+
+ bool useShell;
+ QMap<QString,QString> env;
+ QString wd;
+ QCString shell;
+};
+
+
+OProcess::OProcess(QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+}
+
+OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+ *this << arg0;
+}
+
+OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+ *this << args;
+}
+
+void OProcess::init ( )
+{
+ run_mode = NotifyOnExit;
+ runs = false;
+ pid_ = 0;
+ status = 0;
+ keepPrivs = false;
+ innot = 0;
+ outnot = 0;
+ errnot = 0;
+ communication = NoCommunication;
+ input_data = 0;
+ input_sent = 0;
+ input_total = 0;
+ d = 0;
+
+ if (0 == OProcessController::theOProcessController)
+ {
+ (void) new OProcessController();
+ CHECK_PTR(OProcessController::theOProcessController);
+ }
+
+ OProcessController::theOProcessController->addOProcess(this);
+ out[0] = out[1] = -1;
+ in[0] = in[1] = -1;
+ err[0] = err[1] = -1;
+}
+
+void
+OProcess::setEnvironment(const QString &name, const QString &value)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->env.insert(name, value);
+}
+
+void
+OProcess::setWorkingDirectory(const QString &dir)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->wd = dir;
+}
+
+void
+OProcess::setupEnvironment()
+{
+ if (d)
+ {
+ QMap<QString,QString>::Iterator it;
+ for(it = d->env.begin(); it != d->env.end(); ++it)
+ setenv(QFile::encodeName(it.key()).data(),
+ QFile::encodeName(it.data()).data(), 1);
+ if (!d->wd.isEmpty())
+ chdir(QFile::encodeName(d->wd).data());
+ }
+}
+
+void
+OProcess::setRunPrivileged(bool keepPrivileges)
+{
+ keepPrivs = keepPrivileges;
+}
+
+bool
+OProcess::runPrivileged() const
+{
+ return keepPrivs;
+}
+
+
+OProcess::~OProcess()
+{
+ // destroying the OProcess instance sends a SIGKILL to the
+ // child process (if it is running) after removing it from the
+ // list of valid processes (if the process is not started as
+ // "DontCare")
+
+ OProcessController::theOProcessController->removeOProcess(this);
+ // this must happen before we kill the child
+ // TODO: block the signal while removing the current process from the process list
+
+ if (runs && (run_mode != DontCare))
+ kill(SIGKILL);
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+
+ // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
+ delete d;
+}
+
+void OProcess::detach()
+{
+ OProcessController::theOProcessController->removeOProcess(this);
+
+ runs = false;
+ pid_ = 0;
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+}
+
+bool OProcess::setExecutable(const QString& proc)
+{
+ if (runs) return false;
+
+ if (proc.isEmpty()) return false;
+
+ if (!arguments.isEmpty())
+ arguments.remove(arguments.begin());
+ arguments.prepend(QFile::encodeName(proc));
+
+ return true;
+}
+
+OProcess &OProcess::operator<<(const QStringList& args)
+{
+ QStringList::ConstIterator it = args.begin();
+ for ( ; it != args.end() ; ++it )
+ arguments.append(QFile::encodeName(*it));
+ return *this;
+}
+
+OProcess &OProcess::operator<<(const QCString& arg)
+{
+ return operator<< (arg.data());
+}
+
+OProcess &OProcess::operator<<(const char* arg)
+{
+ arguments.append(arg);
+ return *this;
+}
+
+OProcess &OProcess::operator<<(const QString& arg)
+{
+ arguments.append(QFile::encodeName(arg));
+ return *this;
+}
+
+void OProcess::clearArguments()
+{
+ arguments.clear();
+}
+
+bool OProcess::start(RunMode runmode, Communication comm)
+{
+ uint i;
+ uint n = arguments.count();
+ char **arglist;
+
+ if (runs || (0 == n))
+ {
+ return false; // cannot start a process that is already running
+ // or if no executable has been assigned
+ }
+ run_mode = runmode;
+ status = 0;
+
+ QCString shellCmd;
+ if (d && d->useShell)
+ {
+ if (d->shell.isEmpty())
+ {
+ qWarning( "Could not find a valid shell" );
+ return false;
+ }
+
+ arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
+ for (i=0; i < n; i++)
+ {
+ shellCmd += arguments[i];
+ shellCmd += " "; // CC: to separate the arguments
+ }
+
+ arglist[0] = d->shell.data();
+ arglist[1] = (char *) "-c";
+ arglist[2] = shellCmd.data();
+ arglist[3] = 0;
+ }
+ else
+ {
+ arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
+ for (i=0; i < n; i++)
+ arglist[i] = arguments[i].data();
+ arglist[n]= 0;
+ }
+
+ if (!setupCommunication(comm))
+ qWarning( "Could not setup Communication!");
+
+ // We do this in the parent because if we do it in the child process
+ // gdb gets confused when the application runs from gdb.
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+#ifdef HAVE_INITGROUPS
+ struct passwd *pw = getpwuid(uid);
+#endif
+
+ int fd[2];
+ if (0 > pipe(fd))
+ {
+ fd[0] = fd[1] = 0; // Pipe failed.. continue
+ }
+
+ runs = true;
+
+ QApplication::flushX();
+
+ // WABA: Note that we use fork() and not vfork() because
+ // vfork() has unclear semantics and is not standardized.
+ pid_ = fork();
+
+ if (0 == pid_)
+ {
+ if (fd[0])
+ close(fd[0]);
+ if (!runPrivileged())
+ {
+ setgid(gid);
+#if defined( HAVE_INITGROUPS)
+ if(pw)
+ initgroups(pw->pw_name, pw->pw_gid);
+#endif
+ setuid(uid);
+ }
+ // The child process
+ if(!commSetupDoneC())
+ qWarning( "Could not finish comm setup in child!" );
+
+ setupEnvironment();
+
+ // Matthias
+ if (run_mode == DontCare)
+ setpgid(0,0);
+ // restore default SIGPIPE handler (Harri)
+ struct sigaction act;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigaction(SIGPIPE, &act, 0L);
+
+ // We set the close on exec flag.
+ // Closing of fd[1] indicates that the execvp succeeded!
+ if (fd[1])
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ execvp(arglist[0], arglist);
+ char resultByte = 1;
+ if (fd[1])
+ write(fd[1], &resultByte, 1);
+ _exit(-1);
+ }
+ else if (-1 == pid_)
+ {
+ // forking failed
+
+ runs = false;
+ free(arglist);
+ return false;
+ }
+ else
+ {
+ if (fd[1])
+ close(fd[1]);
+ // the parent continues here
+
+ // Discard any data for stdin that might still be there
+ input_data = 0;
+
+ // Check whether client could be started.
+ if (fd[0]) for(;;)
+ {
+ char resultByte;
+ int n = ::read(fd[0], &resultByte, 1);
+ if (n == 1)
+ {
+ // Error
+ runs = false;
+ close(fd[0]);
+ free(arglist);
+ pid_ = 0;
+ return false;
+ }
+ if (n == -1)
+ {
+ if ((errno == ECHILD) || (errno == EINTR))
+ continue; // Ignore
+ }
+ break; // success
+ }
+ if (fd[0])
+ close(fd[0]);
+
+ if (!commSetupDoneP()) // finish communication socket setup for the parent
+ qWarning( "Could not finish comm setup in parent!" );
+
+ if (run_mode == Block)
+ {
+ commClose();
+
+ // The SIGCHLD handler of the process controller will catch
+ // the exit and set the status
+ while(runs)
+ {
+ OProcessController::theOProcessController->
+ slotDoHousekeeping(0);
+ }
+ runs = FALSE;
+ emit processExited(this);
+ }
+ }
+ free(arglist);
+ return true;
+}
+
+
+
+bool OProcess::kill(int signo)
+{
+ bool rv=false;
+
+ if (0 != pid_)
+ rv= (-1 != ::kill(pid_, signo));
+ // probably store errno somewhere...
+ return rv;
+}
+
+
+
+bool OProcess::isRunning() const
+{
+ return runs;
+}
+
+
+
+pid_t OProcess::pid() const
+{
+ return pid_;
+}
+
+
+
+bool OProcess::normalExit() const
+{
+ int _status = status;
+ return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
+}
+
+
+
+int OProcess::exitStatus() const
+{
+ int _status = status;
+ return WEXITSTATUS((_status));
+}
+
+
+
+bool OProcess::writeStdin(const char *buffer, int buflen)
+{
+ bool rv;
+
+ // if there is still data pending, writing new data
+ // to stdout is not allowed (since it could also confuse
+ // kprocess...
+ if (0 != input_data)
+ return false;
+
+ if (runs && (communication & Stdin))
+ {
+ input_data = buffer;
+ input_sent = 0;
+ input_total = buflen;
+ slotSendData(0);
+ innot->setEnabled(true);
+ rv = true;
+ }
+ else
+ rv = false;
+ return rv;
+}
+
+void OProcess::flushStdin ( )
+{
+ if ( !input_data || ( input_sent == input_total ))
+ return;
+
+ int d1, d2;
+
+ do
+ {
+ d1 = input_total - input_sent;
+ slotSendData ( 0 );
+ d2 = input_total - input_sent;
+ }
+ while ( d2 <= d1 );
+}
+
+void OProcess::suspend()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(false);
+}
+
+void OProcess::resume()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(true);
+}
+
+bool OProcess::closeStdin()
+{
+ bool rv;
+
+ if (communication & Stdin)
+ {
+ communication = (Communication) (communication & ~Stdin);
+ delete innot;
+ innot = 0;
+ close(in[1]);
+ rv = true;
+ }
+ else
+ rv = false;
+ return rv;
+}
+
+bool OProcess::closeStdout()
+{
+ bool rv;
+
+ if (communication & Stdout)
+ {
+ communication = (Communication) (communication & ~Stdout);
+ delete outnot;
+ outnot = 0;
+ close(out[0]);
+ rv = true;
+ }
+ else
+ rv = false;
+ return rv;
+}
+
+bool OProcess::closeStderr()
+{
+ bool rv;
+
+ if (communication & Stderr)
+ {
+ communication = static_cast<Communication>(communication & ~Stderr);
+ delete errnot;
+ errnot = 0;
+ close(err[0]);
+ rv = true;
+ }
+ else
+ rv = false;
+ return rv;
+}
+
+
+/////////////////////////////
+// protected slots //
+/////////////////////////////
+
+
+
+void OProcess::slotChildOutput(int fdno)
+{
+ if (!childOutput(fdno))
+ closeStdout();
+}
+
+
+void OProcess::slotChildError(int fdno)
+{
+ if (!childError(fdno))
+ closeStderr();
+}
+
+
+void OProcess::slotSendData(int)
+{
+ if (input_sent == input_total)
+ {
+ innot->setEnabled(false);
+ input_data = 0;
+ emit wroteStdin(this);
+ }
+ else
+ input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent);
+}
+
+
+
+//////////////////////////////
+// private member functions //
+//////////////////////////////
+
+
+
+void OProcess::processHasExited(int state)
+{
+ if (runs)
+ {
+ runs = false;
+ status = state;
+
+ commClose(); // cleanup communication sockets
+
+ // also emit a signal if the process was run Blocking
+ if (DontCare != run_mode)
+ {
+ emit processExited(this);
+ }
+ }
+}
+
+
+
+int OProcess::childOutput(int fdno)
+{
+ if (communication & NoRead)
+ {
+ int len = -1;
+ emit receivedStdout(fdno, len);
+ errno = 0; // Make sure errno doesn't read "EAGAIN"
+ return len;
+ }
+ else
+ {
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len)
+ {
+ emit receivedStdout(this, buffer, len);
+ }
+ return len;
+ }
+}
+
+
+
+int OProcess::childError(int fdno)
+{
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len)
+ emit receivedStderr(this, buffer, len);
+ return len;
+}
+
+
+
+int OProcess::setupCommunication(Communication comm)
+{
+ int ok;
+
+ communication = comm;
+
+ ok = 1;
+ if (comm & Stdin)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0;
+
+ if (comm & Stdout)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0;
+
+ if (comm & Stderr)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0;
+
+ return ok;
+}
+
+
+
+int OProcess::commSetupDoneP()
+{
+ int ok = 1;
+
+ if (communication != NoCommunication)
+ {
+ if (communication & Stdin)
+ close(in[0]);
+ if (communication & Stdout)
+ close(out[1]);
+ if (communication & Stderr)
+ close(err[1]);
+
+ // Don't create socket notifiers and set the sockets non-blocking if
+ // blocking is requested.
+ if (run_mode == Block) return ok;
+
+ if (communication & Stdin)
+ {
+ // ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));
+ innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this);
+ CHECK_PTR(innot);
+ innot->setEnabled(false); // will be enabled when data has to be sent
+ QObject::connect(innot, SIGNAL(activated(int)),
+ this, SLOT(slotSendData(int)));
+ }
+
+ if (communication & Stdout)
+ {
+ // ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));
+ outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);
+ CHECK_PTR(outnot);
+ QObject::connect(outnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildOutput(int)));
+ if (communication & NoRead)
+ suspend();
+ }
+
+ if (communication & Stderr)
+ {
+ // ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));
+ errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );
+ CHECK_PTR(errnot);
+ QObject::connect(errnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildError(int)));
+ }
+ }
+ return ok;
+}
+
+
+
+int OProcess::commSetupDoneC()
+{
+ int ok = 1;
+ struct linger so;
+ memset(&so, 0, sizeof(so));
+
+ if (communication & Stdin)
+ close(in[1]);
+ if (communication & Stdout)
+ close(out[0]);
+ if (communication & Stderr)
+ close(err[0]);
+
+ if (communication & Stdin)
+ ok &= dup2(in[0], STDIN_FILENO) != -1;
+ else
+ {
+ int null_fd = open( "/dev/null", O_RDONLY );
+ ok &= dup2( null_fd, STDIN_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stdout)
+ {
+ ok &= dup2(out[1], STDOUT_FILENO) != -1;
+ ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));
+ }
+ else
+ {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stderr)
+ {
+ ok &= dup2(err[1], STDERR_FILENO) != -1;
+ ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>(&so), sizeof(so));
+ }
+ else
+ {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDERR_FILENO ) != -1;
+ close( null_fd );
+ }
+ return ok;
+}
+
+
+
+void OProcess::commClose()
+{
+ if (NoCommunication != communication)
+ {
+ bool b_in = (communication & Stdin);
+ bool b_out = (communication & Stdout);
+ bool b_err = (communication & Stderr);
+ if (b_in)
+ delete innot;
+
+ if (b_out || b_err)
+ {
+ // If both channels are being read we need to make sure that one socket buffer
+ // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).
+ // Hence we need to use select.
+
+ // Once one or other of the channels has reached EOF (or given an error) go back
+ // to the usual mechanism.
+
+ int fds_ready = 1;
+ fd_set rfds;
+
+ int max_fd = 0;
+ if (b_out)
+ {
+ fcntl(out[0], F_SETFL, O_NONBLOCK);
+ if (out[0] > max_fd)
+ max_fd = out[0];
+ delete outnot;
+ outnot = 0;
+ }
+ if (b_err)
+ {
+ fcntl(err[0], F_SETFL, O_NONBLOCK);
+ if (err[0] > max_fd)
+ max_fd = err[0];
+ delete errnot;
+ errnot = 0;
+ }
+
+
+ while (b_out || b_err)
+ {
+ // * If the process is still running we block until we
+ // receive data. (p_timeout = 0, no timeout)
+ // * If the process has already exited, we only check
+ // the available data, we don't wait for more.
+ // (p_timeout = &timeout, timeout immediately)
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ struct timeval *p_timeout = runs ? 0 : &timeout;
+
+ FD_ZERO(&rfds);
+ if (b_out)
+ FD_SET(out[0], &rfds);
+
+ if (b_err)
+ FD_SET(err[0], &rfds);
+
+ fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout);
+ if (fds_ready <= 0) break;
+
+ if (b_out && FD_ISSET(out[0], &rfds))
+ {
+ int ret = 1;
+ while (ret > 0) ret = childOutput(out[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_out = false;
+ }
+
+ if (b_err && FD_ISSET(err[0], &rfds))
+ {
+ int ret = 1;
+ while (ret > 0) ret = childError(err[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_err = false;
+ }
+ }
+ }
+
+ if (b_in)
+ {
+ communication = (Communication) (communication & ~Stdin);
+ close(in[1]);
+ }
+ if (b_out)
+ {
+ communication = (Communication) (communication & ~Stdout);
+ close(out[0]);
+ }
+ if (b_err)
+ {
+ communication = (Communication) (communication & ~Stderr);
+ close(err[0]);
+ }
+ }
+}
+
+void OProcess::setUseShell(bool useShell, const char *shell)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->useShell = useShell;
+ d->shell = shell;
+ if (d->shell.isEmpty())
+ d->shell = searchShell();
+}
+
+QString OProcess::quote(const QString &arg)
+{
+ QString res = arg;
+ res.replace(QRegExp(QString::fromLatin1("\'")),
+ QString::fromLatin1("'\"'\"'"));
+ res.prepend('\'');
+ res.append('\'');
+ return res;
+}
+
+QCString OProcess::searchShell()
+{
+ QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace();
+ if (!isExecutable(tmpShell))
+ {
+ tmpShell = "/bin/sh";
+ }
+
+ return tmpShell;
+}
+
+bool OProcess::isExecutable(const QCString &filename)
+{
+ struct stat fileinfo;
+
+ if (filename.isEmpty()) return false;
+
+ // CC: we've got a valid filename, now let's see whether we can execute that file
+
+ if (-1 == stat(filename.data(), &fileinfo)) return false;
+ // CC: return false if the file does not exist
+
+ // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
+ if ( (S_ISDIR(fileinfo.st_mode)) ||
+ (S_ISCHR(fileinfo.st_mode)) ||
+ (S_ISBLK(fileinfo.st_mode)) ||
+#ifdef S_ISSOCK
+ // CC: SYSVR4 systems don't have that macro
+ (S_ISSOCK(fileinfo.st_mode)) ||
+#endif
+ (S_ISFIFO(fileinfo.st_mode)) ||
+ (S_ISDIR(fileinfo.st_mode)) )
+ {
+ return false;
+ }
+
+ // CC: now check for permission to execute the file
+ if (access(filename.data(), X_OK) != 0) return false;
+
+ // CC: we've passed all the tests...
+ return true;
+}
+
+
+
diff --git a/libopie2/opiecore/oprocess.h b/libopie2/opiecore/oprocess.h
new file mode 100644
index 0000000..8dd19b5
--- a/dev/null
+++ b/libopie2/opiecore/oprocess.h
@@ -0,0 +1,747 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther to the Open Palmtop Integrated Environment
+//
+
+#ifndef __kprocess_h__
+#define __kprocess_h__
+
+#include <sys/types.h> // for pid_t
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <qvaluelist.h>
+#include <qcstring.h>
+#include <qobject.h>
+
+class QSocketNotifier;
+class OProcessPrivate;
+
+/**
+ * Child process invocation, monitoring and control.
+ *
+ * @sect General usage and features
+ *
+ *This class allows a KDE and OPIE application to start child processes without having
+ *to worry about UN*X signal handling issues and zombie process reaping.
+ *
+ *@see KProcIO
+ *
+ *Basically, this class distinguishes three different ways of running
+ *child processes:
+ *
+ *@li OProcess::DontCare -- The child process is invoked and both the child
+ *process and the parent process continue concurrently.
+ *
+ *Starting a DontCare child process means that the application is
+ *not interested in any notification to determine whether the
+ *child process has already exited or not.
+ *
+ *@li OProcess::NotifyOnExit -- The child process is invoked and both the
+ *child and the parent process run concurrently.
+ *
+ *When the child process exits, the OProcess instance
+ *corresponding to it emits the Qt signal @ref processExited().
+ *
+ *Since this signal is @em not emitted from within a UN*X
+ *signal handler, arbitrary function calls can be made.
+ *
+ *Be aware: When the OProcess objects gets destructed, the child
+ *process will be killed if it is still running!
+ *This means in particular, that you cannot use a OProcess on the stack
+ *with OProcess::NotifyOnExit.
+ *
+ *@li OProcess::Block -- The child process starts and the parent process
+ *is suspended until the child process exits. (@em Really not recommended
+ *for programs with a GUI.)
+ *
+ *OProcess also provides several functions for determining the exit status
+ *and the pid of the child process it represents.
+ *
+ *Furthermore it is possible to supply command-line arguments to the process
+ *in a clean fashion (no null -- terminated stringlists and such...)
+ *
+ *A small usage example:
+ *<pre>
+ *OProcess *proc = new OProcess;
+ *
+ **proc << "my_executable";
+ **proc << "These" << "are" << "the" << "command" << "line" << "args";
+ *QApplication::connect(proc, SIGNAL(processExited(OProcess *)),
+ * pointer_to_my_object, SLOT(my_objects_slot(OProcess *)));
+ *proc->start();
+ *</pre>
+ *
+ *This will start "my_executable" with the commandline arguments "These"...
+ *
+ *When the child process exits, the respective Qt signal will be emitted.
+ *
+ *@sect Communication with the child process
+ *
+ *OProcess supports communication with the child process through
+ *stdin/stdout/stderr.
+ *
+ *The following functions are provided for getting data from the child
+ *process or sending data to the child's stdin (For more information,
+ *have a look at the documentation of each function):
+ *
+ *@li bool @ref writeStdin(char *buffer, int buflen);
+ *@li -- Transmit data to the child process's stdin.
+ *
+ *@li bool @ref closeStdin();
+ *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)).
+ *Returns false if you try to close stdin for a process that has been started
+ *without a communication channel to stdin.
+ *
+ *@li bool @ref closeStdout();
+ *@li -- Closes the child process's stdout.
+ *Returns false if you try to close stdout for a process that has been started
+ *without a communication channel to stdout.
+ *
+ *@li bool @ref closeStderr();
+ *@li -- Closes the child process's stderr.
+ *Returns false if you try to close stderr for a process that has been started
+ *without a communication channel to stderr.
+ *
+ *
+ *@sect QT signals:
+ *
+ *@li void @ref receivedStdout(OProcess *proc, char *buffer, int buflen);
+ *@li void @ref receivedStderr(OProcess *proc, char *buffer, int buflen);
+ *@li -- Indicates that new data has arrived from either the
+ *child process's stdout or stderr.
+ *
+ *@li void @ref wroteStdin(OProcess *proc);
+ *@li -- Indicates that all data that has been sent to the child process
+ *by a prior call to @ref writeStdin() has actually been transmitted to the
+ *client .
+ *
+ *@author Christian Czezakte e9025461@student.tuwien.ac.at
+ *
+ *
+ **/
+class OProcess : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Modes in which the communication channel can be opened.
+ *
+ * If communication for more than one channel is required,
+ * the values have to be or'ed together, for example to get
+ * communication with stdout as well as with stdin, you would
+ * specify @p Stdin @p | @p Stdout
+ *
+ * If @p NoRead is specified in conjunction with @p Stdout,
+ * no data is actually read from @p Stdout but only
+ * the signal @ref childOutput(int fd) is emitted.
+ */
+ enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4,
+ AllOutput = 6, All = 7,
+ NoRead };
+
+ /**
+ * Run-modes for a child process.
+ */
+ enum RunMode {
+ /**
+ * The application does not receive notifications from the subprocess when
+ * it is finished or aborted.
+ */
+ DontCare,
+ /**
+ * The application is notified when the subprocess dies.
+ */
+ NotifyOnExit,
+ /**
+ * The application is suspended until the started process is finished.
+ */
+ Block };
+
+ /**
+ * Constructor
+ */
+ OProcess(QObject *parent = 0, const char *name = 0);
+ /**
+ * Constructor
+ */
+ OProcess(const QString &arg0, QObject *parent = 0, const char *name = 0);
+ /**
+ * Constructor
+ */
+ OProcess(const QStringList &args, QObject *parent = 0, const char *name = 0);
+
+ /**
+ *Destructor:
+ *
+ * If the process is running when the destructor for this class
+ * is called, the child process is killed with a SIGKILL, but
+ * only if the run mode is not of type @p DontCare.
+ * Processes started as @p DontCare keep running anyway.
+ */
+ virtual ~OProcess();
+
+ /**
+ @deprecated
+
+ The use of this function is now deprecated. -- Please use the
+ "operator<<" instead of "setExecutable".
+
+ Sets the executable to be started with this OProcess object.
+ Returns false if the process is currently running (in that
+ case the executable remains unchanged.)
+
+ @see operator<<
+
+ */
+ bool setExecutable(const QString& proc);
+
+
+ /**
+ * Sets the executable and the command line argument list for this process.
+ *
+ * For example, doing an "ls -l /usr/local/bin" can be achieved by:
+ * <pre>
+ * OProcess p;
+ * ...
+ * p << "ls" << "-l" << "/usr/local/bin"
+ * </pre>
+ *
+ **/
+ OProcess &operator<<(const QString& arg);
+ /**
+ * Similar to previous method, takes a char *, supposed to be in locale 8 bit already.
+ */
+ OProcess &operator<<(const char * arg);
+ /**
+ * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already.
+ */
+ OProcess &operator<<(const QCString & arg);
+
+ /**
+ * Sets the executable and the command line argument list for this process,
+ * in a single method call, or add a list of arguments.
+ **/
+ OProcess &operator<<(const QStringList& args);
+
+ /**
+ * Clear a command line argument list that has been set by using
+ * the "operator<<".
+ */
+ void clearArguments();
+
+ /**
+ * Starts the process.
+ * For a detailed description of the
+ * various run modes and communication semantics, have a look at the
+ * general description of the OProcess class.
+ *
+ * The following problems could cause this function to
+ * return false:
+ *
+ * @li The process is already running.
+ * @li The command line argument list is empty.
+ * @li The starting of the process failed (could not fork).
+ * @li The executable was not found.
+ *
+ * @param comm Specifies which communication links should be
+ * established to the child process (stdin/stdout/stderr). By default,
+ * no communication takes place and the respective communication
+ * signals will never get emitted.
+ *
+ * @return true on success, false on error
+ * (see above for error conditions)
+ **/
+ virtual bool start(RunMode runmode = NotifyOnExit,
+ Communication comm = NoCommunication);
+
+ /**
+ * Stop the process (by sending it a signal).
+ *
+ * @param signo The signal to send. The default is SIGTERM.
+ * @return @p true if the signal was delivered successfully.
+ */
+ virtual bool kill(int signo = SIGTERM);
+
+ /**
+ @return @p true if the process is (still) considered to be running
+ */
+ bool isRunning() const;
+
+ /** Returns the process id of the process.
+ *
+ * If it is called after
+ * the process has exited, it returns the process id of the last
+ * child process that was created by this instance of OProcess.
+ *
+ * Calling it before any child process has been started by this
+ * OProcess instance causes pid() to return 0.
+ **/
+ pid_t pid() const;
+
+ /**
+ * Suspend processing of data from stdout of the child process.
+ */
+ void suspend();
+
+ /**
+ * Resume processing of data from stdout of the child process.
+ */
+ void resume();
+
+ /**
+ * @return @p true if the process has already finished and has exited
+ * "voluntarily", ie: it has not been killed by a signal.
+ *
+ * Note that you should check @ref OProcess::exitStatus() to determine
+ * whether the process completed its task successful or not.
+ */
+ bool normalExit() const;
+
+ /**
+ * Returns the exit status of the process.
+ *
+ * Please use
+ * @ref OProcess::normalExit() to check whether the process has exited
+ * cleanly (i.e., @ref OProcess::normalExit() returns @p true) before calling
+ * this function because if the process did not exit normally,
+ * it does not have a valid exit status.
+ */
+ int exitStatus() const;
+
+
+ /**
+ * Transmit data to the child process's stdin.
+ *
+ * OProcess::writeStdin may return false in the following cases:
+ *
+ * @li The process is not currently running.
+ *
+ * @li Communication to stdin has not been requested in the @ref start() call.
+ *
+ * @li Transmission of data to the child process by a previous call to
+ * @ref writeStdin() is still in progress.
+ *
+ * Please note that the data is sent to the client asynchronously,
+ * so when this function returns, the data might not have been
+ * processed by the child process.
+ *
+ * If all the data has been sent to the client, the signal
+ * @ref wroteStdin() will be emitted.
+ *
+ * Please note that you must not free "buffer" or call @ref writeStdin()
+ * again until either a @ref wroteStdin() signal indicates that the
+ * data has been sent or a @ref processHasExited() signal shows that
+ * the child process is no longer alive...
+ **/
+ bool writeStdin(const char *buffer, int buflen);
+
+ void flushStdin();
+
+ /**
+ * This causes the stdin file descriptor of the child process to be
+ * closed indicating an "EOF" to the child.
+ *
+ * @return @p false if no communication to the process's stdin
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdin();
+
+ /**
+ * This causes the stdout file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stdout
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdout();
+
+ /**
+ * This causes the stderr file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stderr
+ * had been specified in the call to @ref start().
+ */
+ bool closeStderr();
+
+ /**
+ * Lets you see what your arguments are for debugging.
+ */
+
+ const QValueList<QCString> &args() { return arguments; }
+
+ /**
+ * Controls whether the started process should drop any
+ * setuid/segid privileges or whether it should keep them
+ *
+ * The default is @p false : drop privileges
+ */
+ void setRunPrivileged(bool keepPrivileges);
+
+ /**
+ * Returns whether the started process will drop any
+ * setuid/segid privileges or whether it will keep them
+ */
+ bool runPrivileged() const;
+
+ /**
+ * Modifies the environment of the process to be started.
+ * This function must be called before starting the process.
+ */
+ void setEnvironment(const QString &name, const QString &value);
+
+ /**
+ * Changes the current working directory (CWD) of the process
+ * to be started.
+ * This function must be called before starting the process.
+ */
+ void setWorkingDirectory(const QString &dir);
+
+ /**
+ * Specify whether to start the command via a shell or directly.
+ * The default is to start the command directly.
+ * If @p useShell is true @p shell will be used as shell, or
+ * if shell is empty, the standard shell is used.
+ * @p quote A flag indicating whether to quote the arguments.
+ *
+ * When using a shell, the caller should make sure that all filenames etc.
+ * are properly quoted when passed as argument.
+ * @see quote()
+ */
+ void setUseShell(bool useShell, const char *shell = 0);
+
+ /**
+ * This function can be used to quote an argument string such that
+ * the shell processes it properly. This is e. g. necessary for
+ * user-provided file names which may contain spaces or quotes.
+ * It also prevents expansion of wild cards and environment variables.
+ */
+ static QString quote(const QString &arg);
+
+ /**
+ * Detaches OProcess from child process. All communication is closed.
+ * No exit notification is emitted any more for the child process.
+ * Deleting the OProcess will no longer kill the child process.
+ * Note that the current process remains the parent process of the
+ * child process.
+ */
+ void detach();
+
+
+
+signals:
+
+ /**
+ * Emitted after the process has terminated when
+ * the process was run in the @p NotifyOnExit (==default option to
+ * @ref start()) or the @ref Block mode.
+ **/
+ void processExited(OProcess *proc);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ **/
+ void receivedStdout(OProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get these signals, the respective communications link
+ * (stdout/stderr) has to be turned on in @ref start() and the
+ * @p NoRead flag should have been passed.
+ *
+ * You will need to explicitly call resume() after your call to start()
+ * to begin processing data from the child process's stdout. This is
+ * to ensure that this signal is not emitted when no one is connected
+ * to it, otherwise this signal will not be emitted.
+ *
+ * The data still has to be read from file descriptor @p fd.
+ **/
+ void receivedStdout(int fd, int &len);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stderr.
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ */
+ void receivedStderr(OProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted after all the data that has been
+ * specified by a prior call to @ref writeStdin() has actually been
+ * written to the child process.
+ **/
+ void wroteStdin(OProcess *proc);
+
+
+protected slots:
+
+ /**
+ * This slot gets activated when data from the child's stdout arrives.
+ * It usually calls "childOutput"
+ */
+ void slotChildOutput(int fdno);
+
+ /**
+ * This slot gets activated when data from the child's stderr arrives.
+ * It usually calls "childError"
+ */
+ void slotChildError(int fdno);
+ /*
+ Slot functions for capturing stdout and stderr of the child
+ */
+
+ /**
+ * Called when another bulk of data can be sent to the child's
+ * stdin. If there is no more data to be sent to stdin currently
+ * available, this function must disable the QSocketNotifier "innot".
+ */
+ void slotSendData(int dummy);
+
+protected:
+
+ /**
+ * Sets up the environment according to the data passed via
+ * setEnvironment(...)
+ */
+ void setupEnvironment();
+
+ /**
+ * The list of the process' command line arguments. The first entry
+ * in this list is the executable itself.
+ */
+ QValueList<QCString> arguments;
+ /**
+ * How to run the process (Block, NotifyOnExit, DontCare). You should
+ * not modify this data member directly from derived classes.
+ */
+ RunMode run_mode;
+ /**
+ * true if the process is currently running. You should not
+ * modify this data member directly from derived classes. For
+ * reading the value of this data member, please use "isRunning()"
+ * since "runs" will probably be made private in later versions
+ * of OProcess.
+ */
+ bool runs;
+
+ /**
+ * The PID of the currently running process (see "getPid()").
+ * You should not modify this data member in derived classes.
+ * Please use "getPid()" instead of directly accessing this
+ * member function since it will probably be made private in
+ * later versions of OProcess.
+ */
+ pid_t pid_;
+
+ /**
+ * The process' exit status as returned by "waitpid". You should not
+ * modify the value of this data member from derived classes. You should
+ * rather use @ref exitStatus than accessing this data member directly
+ * since it will probably be made private in further versions of
+ * OProcess.
+ */
+ int status;
+
+
+ /**
+ * See setRunPrivileged()
+ */
+ bool keepPrivs;
+
+ /*
+ Functions for setting up the sockets for communication.
+ setupCommunication
+ -- is called from "start" before "fork"ing.
+ commSetupDoneP
+ -- completes communication socket setup in the parent
+ commSetupDoneC
+ -- completes communication setup in the child process
+ commClose
+ -- frees all allocated communication resources in the parent
+ after the process has exited
+ */
+
+ /**
+ * This function is called from "OProcess::start" right before a "fork" takes
+ * place. According to
+ * the "comm" parameter this function has to initialize the "in", "out" and
+ * "err" data member of OProcess.
+ *
+ * This function should return 0 if setting the needed communication channels
+ * was successful.
+ *
+ * The default implementation is to create UNIX STREAM sockets for the communication,
+ * but you could overload this function and establish a TCP/IP communication for
+ * network communication, for example.
+ */
+ virtual int setupCommunication(Communication comm);
+
+ /**
+ * Called right after a (successful) fork on the parent side. This function
+ * will usually do some communications cleanup, like closing the reading end
+ * of the "stdin" communication channel.
+ *
+ * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and
+ * "errnot" and connect their Qt slots to the respective OProcess member functions.
+ *
+ * For a more detailed explanation, it is best to have a look at the default
+ * implementation of "setupCommunication" in kprocess.cpp.
+ */
+ virtual int commSetupDoneP();
+
+ /**
+ * Called right after a (successful) fork, but before an "exec" on the child
+ * process' side. It usually just closes the unused communication ends of
+ * "in", "out" and "err" (like the writing end of the "in" communication
+ * channel.
+ */
+ virtual int commSetupDoneC();
+
+
+ /**
+ * Immediately called after a process has exited. This function normally
+ * calls commClose to close all open communication channels to this
+ * process and emits the "processExited" signal (if the process was
+ * not running in the "DontCare" mode).
+ */
+ virtual void processHasExited(int state);
+
+ /**
+ * Should clean up the communication links to the child after it has
+ * exited. Should be called from "processHasExited".
+ */
+ virtual void commClose();
+
+
+ /**
+ * the socket descriptors for stdin/stdout/stderr.
+ */
+ int out[2];
+ int in[2];
+ int err[2];
+
+ /**
+ * The socket notifiers for the above socket descriptors.
+ */
+ QSocketNotifier *innot;
+ QSocketNotifier *outnot;
+ QSocketNotifier *errnot;
+
+ /**
+ * Lists the communication links that are activated for the child
+ * process. Should not be modified from derived classes.
+ */
+ Communication communication;
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr".
+ */
+ int childOutput(int fdno);
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr"
+ */
+ int childError(int fdno);
+
+ // information about the data that has to be sent to the child:
+
+ const char *input_data; // the buffer holding the data
+ int input_sent; // # of bytes already transmitted
+ int input_total; // total length of input_data
+
+ /**
+ * @ref OProcessController is a friend of OProcess because it has to have
+ * access to various data members.
+ */
+ friend class OProcessController;
+
+
+private:
+ /**
+ * Searches for a valid shell.
+ * Here is the algorithm used for finding an executable shell:
+ *
+ * @li Try the executable pointed to by the "SHELL" environment
+ * variable with white spaces stripped off
+ *
+ * @li If your process runs with uid != euid or gid != egid, a shell
+ * not listed in /etc/shells will not used.
+ *
+ * @li If no valid shell could be found, "/bin/sh" is used as a last resort.
+ */
+ QCString searchShell();
+
+ /**
+ * Used by @ref searchShell in order to find out whether the shell found
+ * is actually executable at all.
+ */
+ bool isExecutable(const QCString &filename);
+
+ // Disallow assignment and copy-construction
+ OProcess( const OProcess& );
+ OProcess& operator= ( const OProcess& );
+
+private:
+ void init ( );
+
+ OProcessPrivate *d;
+};
+
+
+
+#endif
+
diff --git a/libopie2/opienet/libopienet2.control b/libopie2/opienet/libopienet2.control
index 8eb0704..a45eb2d 100644
--- a/libopie2/opienet/libopienet2.control
+++ b/libopie2/opienet/libopienet2.control
@@ -1,11 +1,11 @@
Package: libopienet2
Files: $OPIEDIR/lib/libopienet2.so.* $OPIEDIR/etc/manufacturers
Priority: optional
Section: opie/system
Maintainer: Opie Team <opie@handhelds.org>
Architecture: arm
-Version: 1.8.2-$SUB_VERSION.2
-Depends: libopiecore2 (1.8.2)
+Version: 1.8.3-$SUB_VERSION
+Depends: libopiecore2 (1.8.3)
Provides: libopienet2
Description: Opie library 2.0 NET