From ea3945a9bd8f9830f70b1efa133f9df13b19362f Mon Sep 17 00:00:00 2001 From: mickeyl Date: Tue, 16 Nov 2004 19:14:18 +0000 Subject: libopie1 goes into unsupported --- (limited to 'noncore/unsupported/libopie/odevice.cpp') diff --git a/noncore/unsupported/libopie/odevice.cpp b/noncore/unsupported/libopie/odevice.cpp new file mode 100644 index 0000000..9d0bbbf --- a/dev/null +++ b/noncore/unsupported/libopie/odevice.cpp @@ -0,0 +1,2827 @@ +/* This file is part of the OPIE libraries + Copyright (C) 2002 Robert Griebl (sandman@handhelds.org) + + 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. +*/ + +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_SOUND +#include +#endif +#include + + +#include +#include +#include +#include +#include +#include + +#include "odevice.h" + +#include + +#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 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 *m_buttons; + uint m_holdtime; + QStrList *m_cpu_frequencies; + +}; + +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 ledList ( ) const; + virtual QValueList 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]; +}; + +class Jornada : public ODevice { +protected: + virtual void init ( ); + //virtual void initButtons ( ); +public: + virtual bool setSoftSuspend ( bool soft ); + virtual bool setDisplayBrightness ( int b ); + virtual int displayBrightnessResolution ( ) const; + static bool isJornada(); + +}; + +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 ledList ( ) const; + virtual QValueList ledStateList ( OLed led ) const; + virtual OLedState ledState ( OLed led ) const; + virtual bool setLedState ( OLed led, OLedState st ); + + bool hasHingeSensor() const; + OHingeStatus readHingeSensor(); + + static bool isZaurus(); + + // Does this break BC? + virtual bool suspend ( ); + Transformation rotation ( ) const; + ODirection direction ( ) const; + +protected: + virtual void buzzer ( int snd ); + + OLedState m_leds [1]; + bool m_embedix; + void virtual_hook( int id, void *data ); +}; + +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 ledList ( ) const; + virtual QValueList 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]; //FIXME check if really only one +}; + +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 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()" }, +}; + +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()" }, +}; + +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()" }, + */ +}; + +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()" }, +}; + +static QCString makeChannel ( const char *str ) +{ + if ( str && !::strchr ( str, '/' )) + return QCString ( "QPE/Application/" ) + str; + else + return str; +} + +static inline bool isQWS() +{ + return qApp ? ( qApp-> type ( ) == QApplication::GuiServer ) : false; +} + +ODevice *ODevice::inst ( ) +{ + static ODevice *dev = 0; + + 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 ( Yopy::isYopy() ) + dev = new Yopy ( ); + else if ( Jornada::isJornada() ) + dev = new Jornada ( ); + else if ( QFile::exists ( "/proc/sys/board/sys_name" )) + dev = new Ramses ( ); + else + dev = new ODevice ( ); + dev-> init ( ); + } + return dev; +} + + +/************************************************** + * + * common + * + **************************************************/ + + +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; + + // Simulation uses iPAQ 3660 device buttons + + qDebug ( "init Buttons" ); + d-> m_buttons = new QValueList ; + + 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&))); +} + +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 + +#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 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; + +#ifdef QT_QWS_DEVFS + if (( fd = ::open ( "/dev/fb/0", O_RDWR )) >= 0 ) { +#else + if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) { +#endif + 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 +{ + VirtRotation rot; + ODevice* that =(ODevice* )this; + that->virtual_hook( VIRTUAL_ROTATION, &rot ); + return rot.trans; +} + +/** + * @return the current rotation direction + */ +ODirection ODevice::direction ( ) const +{ + VirtDirection dir; + ODevice* that =(ODevice* )this; + that->virtual_hook( VIRTUAL_DIRECTION, &dir ); + return dir.direct; +} + +/** + * 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 ODevice::ledList ( ) const +{ + return QValueList ( ); +} + +/** + * This does return the state of the LEDs + */ +QValueList ODevice::ledStateList ( OLed /*which*/ ) const +{ + return QValueList ( ); +} + +/** + * @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 +{ + VirtHasHinge hing; + ODevice* that =(ODevice* )this; + that->virtual_hook( VIRTUAL_HAS_HINGE, &hing ); + return hing.hasHinge; +} + +/** + * @return a value from the hinge sensor + */ +OHingeStatus ODevice::readHingeSensor ( ) +{ + VirtHingeStatus hing; + virtual_hook( VIRTUAL_HINGE, &hing ); + return hing.hingeStat; +} + +/** + * @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 &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 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 id, void* data){ + switch( id ) { + case VIRTUAL_ROTATION:{ + VirtRotation* rot = reinterpret_cast( data ); + rot->trans = d->m_rotation; + break; + } + case VIRTUAL_DIRECTION:{ + VirtDirection *dir = reinterpret_cast( data ); + dir->direct = d->m_direction; + break; + } + case VIRTUAL_HAS_HINGE:{ + VirtHasHinge *hin = reinterpret_cast( data ); + hin->hasHinge = false; + break; + } + case VIRTUAL_HINGE:{ + VirtHingeStatus *hin = reinterpret_cast( data ); + hin->hingeStat = CASE_UNKNOWN; + break; + } + } +} + +/************************************************** + * + * Yopy 3500/3700 + * + **************************************************/ + +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 ; + + 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; +} + +/************************************************** + * + * iPAQ + * + **************************************************/ + +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 ; + + 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&))); +} + + +//#include // including kernel headers is evil ... + +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 ) + + +QValueList iPAQ::ledList ( ) const +{ + QValueList vl; + vl << Led_Power; + + if ( d-> m_model == Model_iPAQ_H38xx ) + vl << Led_BlueTooth; + return vl; +} + +QValueList iPAQ::ledStateList ( OLed l ) const +{ + QValueList 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° or 270° + 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; + } + // Rotate the cursor keys by 270° + // keycode - Key_Left = position of the button starting from left clockwise + // add the rotation to it and modolo. No we've the original offset + // add the offset to the Key_Left key + if ( d-> m_model == Model_iPAQ_H5xxx ) + newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 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; +} + +/************************************************** + * + * Zaurus + * + **************************************************/ + +// 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)"; + } + + 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 ; + + 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 +#include +#include + +//#include // 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 // 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 Zaurus::ledList ( ) const +{ + QValueList vl; + vl << Led_Mail; + return vl; +} + +QValueList Zaurus::ledStateList ( OLed l ) const +{ + QValueList 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( retval ); + } + else + { + qWarning("Zaurus::readHingeSensor() - couldn't compute hinge status!" ); + return CASE_UNKNOWN; + } + } +} + + +void Zaurus::virtual_hook( int id, void *data ) { + switch( id ) { + case VIRTUAL_ROTATION:{ + VirtRotation* rot = reinterpret_cast( data ); + rot->trans = rotation(); + break; + } + case VIRTUAL_DIRECTION:{ + VirtDirection *dir = reinterpret_cast( data ); + dir->direct = direction(); + break; + } + case VIRTUAL_HAS_HINGE:{ + VirtHasHinge *hin = reinterpret_cast( data ); + hin->hasHinge = hasHingeSensor(); + break; + } + case VIRTUAL_HINGE:{ + VirtHingeStatus *hin = reinterpret_cast( data ); + hin->hingeStat = readHingeSensor(); + break; + } + default: + ODevice::virtual_hook( id, data ); + break; + } +} + +/************************************************** + * + * SIMpad + * + **************************************************/ + +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 ; + + 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 SIMpad::ledList ( ) const +{ + QValueList 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 SIMpad::ledStateList ( OLed l ) const +{ + QValueList 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 ) +{ + static int fd = ::open ( SIMPAD_BOARDCONTROL, 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; + } + + { + /*TODO Implement this like that: + read from cs3 + && with SIMPAD_LED2_ON + write to cs3 */ + m_leds [0] = st; + return true; + } + } + } + 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; + ::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; + + 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 +} + +/************************************************** + * + * Ramses + * + **************************************************/ + +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 = Rot90; + 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; +} + + +/************************************************** + * * + * Jornada * + * * + **************************************************/ + + +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 ; + + 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 +{ + return 255; +} + +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; +} -- cgit v0.9.0.2