Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

odevice_zaurus.cpp

Go to the documentation of this file.
00001 /*
00002                              This file is part of the Opie Project
00003                              Copyright (C) 2002-2005 The Opie Team <opie-devel@handhelds.org>
00004               =.             Copyright (C) 2002-2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
00005             .=l.
00006            .>+-=
00007  _;:,     .>    :=|.         This program is free software; you can
00008 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00009 :`=1 )Y*s>-.--   :           the terms of the GNU Library General Public
00010 .="- .-=="i,     .._         License as published by the Free Software
00011  - .   .-<_>     .<>         Foundation; version 2 of the License.
00012      ._= =}       :
00013     .%`+i>       _;_.
00014     .i_,=:_.      -<s.       This program is distributed in the hope that
00015      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00016     : ..    .:,     . . .    without even the implied warranty of
00017     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00018   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00019 ..}^=.=       =       ;      Library General Public License for more
00020 ++=   -.     .`     .:       details.
00021  :     =  ...= . :.=-
00022  -.   .:....=;==+<;          You should have received a copy of the GNU
00023   -_. . .   )=.  =           Library General Public License along with
00024     --        :-=`           this library; see the file COPYING.LIB.
00025                              If not, write to the Free Software Foundation,
00026                              Inc., 59 Temple Place - Suite 330,
00027                              Boston, MA 02111-1307, USA.
00028 */
00029 
00030 #include "odevice_zaurus.h"
00031 
00032 /* OPIE */
00033 #include <opie2/oinputsystem.h>
00034 #include <opie2/oresource.h>
00035 
00036 #include <qpe/config.h>
00037 #include <qpe/sound.h>
00038 
00039 /* QT */
00040 #include <qapplication.h>
00041 #include <qfile.h>
00042 #include <qtextstream.h>
00043 #include <qwindowsystem_qws.h>
00044 #include <qcopchannel_qws.h>
00045 
00046 /* STD */
00047 #include <string.h>
00048 #include <errno.h>
00049 #include <fcntl.h>
00050 #include <math.h>
00051 #include <stdlib.h>
00052 #include <signal.h>
00053 #include <sys/ioctl.h>
00054 #include <sys/time.h>
00055 #include <unistd.h>
00056 #ifndef QT_NO_SOUND
00057 #include <linux/soundcard.h>
00058 #endif
00059 
00060 using namespace Opie::Core;
00061 using namespace Opie::Core::Internal;
00062 
00063 struct z_button z_buttons [] = {
00064     { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
00065     "devicebuttons/z_calendar",
00066     "datebook", "nextView()",
00067     "today", "raise()" },
00068     { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
00069     "devicebuttons/z_contact",
00070     "addressbook", "raise()",
00071     "addressbook", "beamBusinessCard()" },
00072     { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
00073     "devicebuttons/z_home",
00074     "QPE/Launcher", "home()",
00075     "buttonsettings", "raise()" },
00076     { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
00077     "devicebuttons/z_menu",
00078     "QPE/TaskBar", "toggleMenu()",
00079     "QPE/TaskBar", "toggleStartMenu()" },
00080     { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
00081     "devicebuttons/z_mail",
00082     "opiemail", "raise()",
00083     "opiemail", "newMail()" },
00084 };
00085 
00086 struct z_button z_buttons_c700 [] = {
00087     { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
00088     "devicebuttons/z_calendar",
00089     "datebook", "nextView()",
00090     "today", "raise()" },
00091     { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
00092     "devicebuttons/z_contact",
00093     "addressbook", "raise()",
00094     "addressbook", "beamBusinessCard()" },
00095     { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
00096     "devicebuttons/z_home",
00097     "QPE/Launcher", "home()",
00098     "buttonsettings", "raise()" },
00099     { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
00100     "devicebuttons/z_menu",
00101     "QPE/TaskBar", "toggleMenu()",
00102     "QPE/TaskBar", "toggleStartMenu()" },
00103     { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
00104     "devicebuttons/z_mail",
00105     "opiemail", "raise()",
00106     "opiemail", "newMail()" },
00107 
00108     { Qt::Key_F15, QT_TRANSLATE_NOOP("Button", "Hinge1"),
00109     "devicebuttons/z_hinge1",
00110     "QPE/Rotation", "rotateDefault()",0},
00111     { Qt::Key_F16, QT_TRANSLATE_NOOP("Button", "Hinge2"),
00112     "devicebuttons/z_hinge2",
00113     "QPE/Rotation", "rotateDefault()",0},
00114     { Qt::Key_F17, QT_TRANSLATE_NOOP("Button", "Hinge3"),
00115     "devicebuttons/z_hinge3",
00116     "QPE/Rotation", "rotateDefault()",0},
00117 };
00118 
00119 struct z_button z_buttons_6000 [] = {
00120     { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
00121     "devicebuttons/z_calendar",
00122     "datebook", "nextView()",
00123     "today", "raise()" },
00124     { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
00125     "devicebuttons/z_contact",
00126     "addressbook", "raise()",
00127     "addressbook", "beamBusinessCard()" },
00128     { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
00129     "devicebuttons/z_home",
00130     "QPE/Launcher", "home()",
00131     "buttonsettings", "raise()" },
00132     { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
00133     "devicebuttons/z_menu",
00134     "QPE/TaskBar", "toggleMenu()",
00135     "QPE/TaskBar", "toggleStartMenu()" },
00136     { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
00137     "devicebuttons/z_mail",
00138     "opiemail", "raise()",
00139     "opiemail", "newMail()" },
00140     { Qt::Key_F15, QT_TRANSLATE_NOOP("Button", "Rotate Button"),
00141     "devicebuttons/z_rotate",
00142     0,
00143     "QPE/Rotation", "rotateDefault()" },
00144     { Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
00145     "devicebuttons/z_hinge3",
00146     "QPE/VMemo", "toggleRecord()",
00147     "sound", "raise()" },
00148 };
00149 
00150 // FIXME This gets unnecessary complicated. We should think about splitting the Zaurus
00151 //       class up into individual classes. We would need three classes
00152 //
00153 //       Zaurus-Collie (SA-model  w/ 320x240 lcd, for SL5500 and SL5000)
00154 //       Zaurus-Poodle (PXA-model w/ 320x240 lcd, for SL5600)
00155 //       Zaurus-Corgi  (PXA-model w/ 640x480 lcd, for C700, C750, C760, C860, C3000, C1000, C3100)
00156 //       Zaurus-Tosa   (PXA-model w/ 480x640 lcd, for SL6000)
00157 
00158 void Zaurus::init(const QString& cpu_info)
00159 {
00160     qDebug( "Zaurus::init()" );
00161     // Set the time to wait until the system is really suspended
00162     // the delta between apm --suspend and sleeping
00163     setAPMTimeOut( 15000 );
00164 
00165     // generic distribution code already scanned /etc/issue at that point -
00166     // embedix releases contain "Embedix <version> | Linux for Embedded Devices"
00167     if ( d->m_sysverstr.contains( "embedix", false ) )
00168     {
00169         d->m_vendorstr = "Sharp";
00170         d->m_vendor = Vendor_Sharp;
00171         d->m_systemstr = "Zaurus";
00172         d->m_system = System_Zaurus;
00173         m_embedix = true;
00174     }
00175     else
00176     {
00177         d->m_vendorstr = "OpenZaurus Team";
00178         d->m_systemstr = "OpenZaurus";
00179         d->m_system = System_OpenZaurus;
00180         // sysver already gathered
00181 
00182         // OpenZaurus sometimes uses the 2.4 (embedix) kernel, check if this is one
00183         FILE *uname = popen("uname -r", "r");
00184         QFile f;
00185         QString line;
00186         if ( f.open(IO_ReadOnly, uname) ) {
00187             QTextStream ts ( &f );
00188             line = ts.readLine();
00189             m_embedix = line.startsWith( "2.4." );
00190             f.close();
00191         }
00192         pclose(uname);
00193     }
00194 
00195     // check the Zaurus model
00196     QString model;
00197     int loc = cpu_info.find( ":" );
00198     if ( loc != -1 )
00199         model = cpu_info.mid( loc+2 ).simplifyWhiteSpace();
00200     else
00201         model = cpu_info;
00202 
00203     if ( model == "SHARP Corgi" ) {
00204         d->m_model = Model_Zaurus_SLC7x0;
00205         d->m_modelstr = "Zaurus SL-C700";
00206     } else if ( model == "SHARP Shepherd" ) {
00207         d->m_model = Model_Zaurus_SLC7x0;
00208         d->m_modelstr = "Zaurus SL-C750";
00209     } else if ( model == "SHARP Husky" ) {
00210         d->m_model = Model_Zaurus_SLC7x0;
00211         d->m_modelstr = "Zaurus SL-C760 or SL-C860";
00212     } else if ( model == "SHARP Boxer" ) {
00213         d->m_model = Model_Zaurus_SLC7x0;
00214         d->m_modelstr = "Zaurus SL-C760 or SL-C860";
00215     } else if ( model == "SHARP Poodle" ) {
00216         d->m_model = Model_Zaurus_SLB600;
00217         d->m_modelstr = "Zaurus SL-B500 or SL-5600";
00218     } else if ( model == "Sharp-Collie" || model == "Collie" ) {
00219         d->m_model = Model_Zaurus_SL5500;
00220         d->m_modelstr = "Zaurus SL-5500 or SL-5000d";
00221     } else if ( model == "SHARP Tosa" ) {
00222         d->m_model = Model_Zaurus_SL6000;
00223         d->m_modelstr = "Zaurus SL-6000";
00224     } else if ( model == "SHARP Spitz" ) {
00225         d->m_model = Model_Zaurus_SLC3000;
00226         d->m_modelstr = "Zaurus SL-C3000";
00227     } else if ( model == "SHARP Akita" ) {
00228         d->m_model = Model_Zaurus_SLC1000;
00229         d->m_modelstr = "Zaurus SL-C1000";
00230     } else if ( model == "SHARP Borzoi" ) {
00231         d->m_model = Model_Zaurus_SLC3100;
00232         d->m_modelstr = "Zaurus SL-C3100";
00233     } else {
00234         d->m_model = Model_Zaurus_SL5500;
00235         d->m_modelstr = "Unknown Zaurus";
00236     }
00237 
00238     // set path to backlight device in kernel 2.6
00239     switch ( d->m_model )
00240     {
00241         case Model_Zaurus_SLB600: // fallthrough
00242         case Model_Zaurus_SL5500:
00243             m_backlightdev = "/sys/class/backlight/locomo-backlight/";
00244             break;
00245         case Model_Zaurus_SL6000:
00246             m_backlightdev = "/sys/class/backlight/tosa-bl/";
00247             break;
00248         default:
00249             m_backlightdev = "/sys/class/backlight/corgi-bl/";
00250     }
00251 
00252     // set initial rotation
00253     switch( d->m_model )
00254     {
00255         case Model_Zaurus_SL6000: // fallthrough
00256         case Model_Zaurus_SLA300:
00257             d->m_rotation = Rot0;
00258             break;
00259         case Model_Zaurus_SLC3100: // fallthrough
00260         case Model_Zaurus_SLC3000: // fallthrough
00261         case Model_Zaurus_SLC1000: // fallthrough
00262         case Model_Zaurus_SLC7x0:
00263             initHingeSensor();
00264             d->m_rotation = rotation();
00265             d->m_direction = direction();
00266             break;
00267         case Model_Zaurus_SLB600: // fallthrough
00268         case Model_Zaurus_SL5000: // fallthrough
00269         case Model_Zaurus_SL5500: // fallthrough
00270         default:
00271             d->m_rotation = Rot270;
00272     }
00273 
00274     // set default qte driver
00275     switch( d->m_model )
00276     {
00277         case Model_Zaurus_SLC7x0:
00278             d->m_qteDriver = "W100";
00279             break;
00280         default:
00281             d->m_qteDriver = "Transformed";
00282     }
00283 
00284     m_leds[0] = Led_Off;
00285 
00286     if ( m_embedix )
00287         qDebug( "Zaurus::init() - Using the 2.4 Embedix HAL on a %s", (const char*) d->m_modelstr );
00288     else
00289         qDebug( "Zaurus::init() - Using the 2.6 OpenZaurus HAL on a %s", (const char*) d->m_modelstr );
00290 }
00291 
00292 void Zaurus::initButtons()
00293 {
00294     qDebug( "Zaurus::initButtons()" );
00295     if ( d->m_buttons )
00296         return;
00297 
00298     d->m_buttons = new QValueList <ODeviceButton>;
00299 
00300     struct z_button * pz_buttons;
00301     int buttoncount;
00302     switch ( d->m_model )
00303     {
00304         case Model_Zaurus_SL6000:
00305             pz_buttons = z_buttons_6000;
00306             buttoncount = ARRAY_SIZE(z_buttons_6000);
00307             break;
00308         case Model_Zaurus_SLC3100: // fallthrough
00309         case Model_Zaurus_SLC3000: // fallthrough
00310         case Model_Zaurus_SLC1000: // fallthrough
00311         case Model_Zaurus_SLC7x0:
00312             if ( isQWS( ) )
00313             {
00314                 addPreHandler(this);
00315             }
00316             pz_buttons = z_buttons_c700;
00317             buttoncount = ARRAY_SIZE(z_buttons_c700);
00318             break;
00319         default:
00320             pz_buttons = z_buttons;
00321             buttoncount = ARRAY_SIZE(z_buttons);
00322             break;
00323     }
00324 
00325     for ( int i = 0; i < buttoncount; i++ ) {
00326         struct z_button *zb = pz_buttons + i;
00327         ODeviceButton b;
00328 
00329         b.setKeycode( zb->code );
00330         b.setUserText( QObject::tr( "Button", zb->utext ));
00331         b.setPixmap( OResource::loadPixmap( zb->pix ));
00332         b.setFactoryPresetPressedAction( OQCopMessage( makeChannel ( zb->fpressedservice ), zb->fpressedaction ));
00333         b.setFactoryPresetHeldAction( OQCopMessage( makeChannel ( zb->fheldservice ), zb->fheldaction ));
00334         d->m_buttons->append( b );
00335     }
00336 
00337     reloadButtonMapping();
00338 }
00339 
00340 
00341 
00342 typedef struct sharp_led_status {
00343     int which;   /* select which LED status is wanted. */
00344     int status;  /* set new led status if you call SHARP_LED_SETSTATUS */
00345 } sharp_led_status;
00346 
00347 void Zaurus::buzzer( int sound )
00348 {
00349 #ifndef QT_NO_SOUND
00350     Sound *snd = 0;
00351 
00352     // All devices except SL5500 have a DSP device
00353     if ( d->m_model != Model_Zaurus_SL5000
00354       && d->m_model != Model_Zaurus_SL5500 ) {
00355 
00356         switch ( sound ){
00357         case SHARP_BUZ_TOUCHSOUND: {
00358             static Sound touch_sound("touchsound");
00359             snd = &touch_sound;
00360     }
00361             break;
00362         case SHARP_BUZ_KEYSOUND: {
00363             static Sound key_sound( "keysound" );
00364             snd = &key_sound;
00365     }
00366             break;
00367         case SHARP_BUZ_SCHEDULE_ALARM:
00368         default: {
00369             static Sound alarm_sound("alarm");
00370             snd = &alarm_sound;
00371     }
00372             break;
00373         }
00374     }
00375 
00376     // If a soundname is defined, we expect that this device has
00377     // sound capabilities.. Otherwise we expect to have the buzzer
00378     // device..
00379     if ( snd && snd->isFinished() ){
00380         changeMixerForAlarm( 0, "/dev/sound/mixer", snd );
00381         snd->play();
00382     } else if( !snd ) {
00383         int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK );
00384 
00385         if ( fd >= 0 ) {
00386             ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound );
00387             ::close ( fd );
00388         }
00389 
00390     }
00391 #endif
00392 }
00393 
00394 
00395 void Zaurus::playAlarmSound()
00396 {
00397     buzzer( SHARP_BUZ_SCHEDULE_ALARM );
00398 }
00399 
00400 void Zaurus::playTouchSound()
00401 {
00402     buzzer( SHARP_BUZ_TOUCHSOUND );
00403 }
00404 
00405 void Zaurus::playKeySound()
00406 {
00407     buzzer( SHARP_BUZ_KEYSOUND );
00408 }
00409 
00410 
00411 QValueList <OLed> Zaurus::ledList() const
00412 {
00413     QValueList <OLed> vl;
00414     vl << Led_Mail;
00415     return vl;
00416 }
00417 
00418 QValueList <OLedState> Zaurus::ledStateList( OLed l ) const
00419 {
00420     QValueList <OLedState> vl;
00421 
00422     if ( l == Led_Mail )
00423         vl << Led_Off << Led_On << Led_BlinkSlow;
00424     return vl;
00425 }
00426 
00427 OLedState Zaurus::ledState( OLed which ) const
00428 {
00429     if ( which == Led_Mail )
00430         return m_leds [0];
00431     else
00432         return Led_Off;
00433 }
00434 
00435 bool Zaurus::setLedState( OLed which, OLedState st )
00436 {
00437      // Currently not supported on non_embedix kernels
00438     if (!m_embedix)
00439     {
00440         qDebug( "Zaurus::setLedState: ODevice handling for non-embedix kernels not yet implemented" );
00441         return false;
00442     }
00443 
00444     static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK );
00445 
00446     if ( which == Led_Mail ) {
00447         if ( fd >= 0 ) {
00448             struct sharp_led_status leds;
00449             ::memset ( &leds, 0, sizeof( leds ));
00450             leds. which = SHARP_LED_MAIL_EXISTS;
00451             bool ok = true;
00452 
00453             switch ( st ) {
00454                 case Led_Off      : leds. status = LED_MAIL_NO_UNREAD_MAIL; break;
00455                 case Led_On       : leds. status = LED_MAIL_NEWMAIL_EXISTS; break;
00456                 case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break;
00457                 default            : ok = false;
00458             }
00459 
00460             if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) {
00461                 m_leds [0] = st;
00462                 return true;
00463             }
00464         }
00465     }
00466     return false;
00467 }
00468 
00469 int Zaurus::displayBrightnessResolution() const
00470 {
00471     int res = 1;
00472     if (m_embedix)
00473     {
00474         int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_RDWR|O_NONBLOCK );
00475         if ( fd )
00476         {
00477             int value = ::ioctl( fd, SHARP_FL_IOCTL_GET_STEP, 0 );
00478             ::close( fd );
00479             return value ? value : res;
00480         }
00481     }
00482     else
00483     {
00484         int fd = ::open( m_backlightdev + "max_brightness", O_RDONLY|O_NONBLOCK );
00485         if ( fd )
00486         {
00487             char buf[100];
00488             if ( ::read( fd, &buf[0], sizeof buf ) ) ::sscanf( &buf[0], "%d", &res );
00489             ::close( fd );
00490         }
00491     }
00492     return res;
00493 }
00494 
00495 bool Zaurus::setDisplayBrightness( int bright )
00496 {
00497     //qDebug( "Zaurus::setDisplayBrightness( %d )", bright );
00498     bool res = false;
00499 
00500     if ( bright > 255 ) bright = 255;
00501     if ( bright < 0 ) bright = 0;
00502 
00503     int numberOfSteps = displayBrightnessResolution();
00504     int val = ( bright == 1 ) ? 1 : ( bright * numberOfSteps ) / 255;
00505 
00506     if ( m_embedix )
00507     {
00508         int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_WRONLY|O_NONBLOCK );
00509         if ( fd )
00510         {
00511             res = ( ::ioctl( fd, SHARP_FL_IOCTL_STEP_CONTRAST, val ) == 0 );
00512             ::close( fd );
00513         }
00514     }
00515     else
00516     {
00517         int fd = ::open( m_backlightdev + "brightness", O_WRONLY|O_NONBLOCK );
00518         if ( fd )
00519         {
00520             char buf[100];
00521             int len = ::snprintf( &buf[0], sizeof buf, "%d", val );
00522             res = ( ::write( fd, &buf[0], len ) == 0 );
00523             ::close( fd );
00524         }
00525     }
00526     return res;
00527 }
00528 
00529 bool Zaurus::setDisplayStatus( bool on )
00530 {
00531     bool res = false;
00532     if ( m_embedix )
00533     {
00534         int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_WRONLY|O_NONBLOCK );
00535         if ( fd )
00536         {
00537             int ioctlnum = on ? SHARP_FL_IOCTL_ON : SHARP_FL_IOCTL_OFF;
00538             res = ( ::ioctl ( fd, ioctlnum, 0 ) == 0 );
00539             ::close ( fd );
00540         }
00541     }
00542     else
00543     {
00544         int fd = ::open( m_backlightdev + "power", O_WRONLY|O_NONBLOCK );
00545         if ( fd )
00546         {
00547             char buf[10];
00548             buf[0] = on ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
00549             buf[1] = '\0';
00550             res = ( ::write( fd, &buf[0], 2 ) == 0 );
00551             ::close( fd );
00552         }
00553     }
00554     return res;
00555 }
00556 
00557 Transformation Zaurus::rotation() const
00558 {
00559     qDebug( "Zaurus::rotation()" );
00560     Transformation rot;
00561 
00562     switch ( d->m_model ) {
00563         case Model_Zaurus_SLC3100: // fallthrough
00564         case Model_Zaurus_SLC3000: // fallthrough
00565         case Model_Zaurus_SLC1000:
00566         {
00567             OHingeStatus hs = readHingeSensor();
00568             qDebug( "Zaurus::rotation() - hinge sensor = %d", (int) hs );
00569             if ( hs == CASE_PORTRAIT ) rot = Rot0;
00570             else if ( hs == CASE_UNKNOWN ) rot = Rot270;
00571             else rot = Rot270;
00572         }
00573         break;
00574 
00575         // SLC7x0 needs a special case here, because we were able to set the W100
00576         // hardware default rotation on kernel 2.6 to Rot0
00577         case Model_Zaurus_SLC7x0:
00578         {
00579             OHingeStatus hs = readHingeSensor();
00580             qDebug( "Zaurus::rotation() - hinge sensor = %d", (int) hs );
00581 
00582             if ( m_embedix )
00583             {
00584                 if ( hs == CASE_PORTRAIT ) rot = Rot0;
00585                 else if ( hs == CASE_UNKNOWN ) rot = Rot270;
00586                 else rot = Rot270;
00587             }
00588             else
00589             {
00590                 if ( hs == CASE_PORTRAIT ) rot = Rot90;
00591                 else if ( hs == CASE_UNKNOWN ) rot = Rot0;
00592                 else rot = Rot0;
00593             }
00594         }
00595         break;
00596         case Model_Zaurus_SL6000:
00597         case Model_Zaurus_SLB600:
00598         case Model_Zaurus_SLA300:
00599         case Model_Zaurus_SL5500:
00600         case Model_Zaurus_SL5000:
00601         default:
00602             rot = d->m_rotation;
00603             break;
00604     }
00605 
00606     qDebug( "Zaurus::rotation() - returning '%d'", rot );
00607     return rot;
00608 }
00609 ODirection Zaurus::direction() const
00610 {
00611     ODirection dir;
00612 
00613     switch ( d->m_model ) {
00614         case Model_Zaurus_SLC3100: // fallthrough
00615         case Model_Zaurus_SLC3000: // fallthrough
00616         case Model_Zaurus_SLC1000: // fallthrough
00617         case Model_Zaurus_SLC7x0: {
00618                 OHingeStatus hs = readHingeSensor();
00619                 if ( hs == CASE_PORTRAIT ) dir = CCW;
00620                 else if ( hs == CASE_UNKNOWN ) dir = CCW;
00621                 else dir = CW;
00622             }
00623             break;
00624         case Model_Zaurus_SL6000:
00625         case Model_Zaurus_SLA300:
00626         case Model_Zaurus_SLB600:
00627         case Model_Zaurus_SL5500:
00628         case Model_Zaurus_SL5000:
00629         default: dir = d->m_direction;
00630             break;
00631     }
00632     return dir;
00633 
00634 }
00635 
00636 bool Zaurus::hasHingeSensor() const
00637 {
00638     return d->m_model == Model_Zaurus_SLC7x0 ||
00639            d->m_model == Model_Zaurus_SLC3100 ||
00640            d->m_model == Model_Zaurus_SLC3000 ||
00641            d->m_model == Model_Zaurus_SLC1000;
00642 }
00643 
00644 OHingeStatus Zaurus::readHingeSensor() const
00645 {
00646     if (m_embedix)
00647     {
00648         int handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
00649         if (handle == -1)
00650         {
00651             qWarning("Zaurus::readHingeSensor() - failed (%s)", "unknown reason" ); //FIXME: use strerror
00652             return CASE_UNKNOWN;
00653         }
00654         else
00655         {
00656             int retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
00657             ::close (handle);
00658             if ( retval == CASE_CLOSED || retval == CASE_PORTRAIT || retval == CASE_LANDSCAPE )
00659             {
00660                 qDebug( "Zaurus::readHingeSensor() - result = %d", retval );
00661                 return static_cast<OHingeStatus>( retval );
00662             }
00663             else
00664             {
00665                 qWarning("Zaurus::readHingeSensor() - couldn't compute hinge status!" );
00666                 return CASE_UNKNOWN;
00667             }
00668         }
00669     }
00670     else
00671     {
00672         /*
00673          * The corgi keyboard is event source 0 in OZ kernel 2.6.
00674          * Hinge status is reported via Input System Switchs 0 and 1 like that:
00675          *
00676          * -------------------------
00677          * | SW0 | SW1 |    CASE   |
00678          * |-----|-----|-----------|
00679          * |  0     0    Landscape |
00680          * |  0     1    Portrait  |
00681          * |  1     0    Unknown   |
00682          * |  1     1    Closed    |
00683          * -------------------------
00684          */
00685         OInputDevice* keyboard = OInputSystem::instance()->device( "event0" );
00686         bool switch0 = true;
00687         bool switch1 = false;
00688         if ( keyboard )
00689         {
00690             switch0 = keyboard->isHeld( OInputDevice::Switch0 );
00691             switch1 = keyboard->isHeld( OInputDevice::Switch1 );
00692         }
00693         if ( switch0 )
00694         {
00695             return switch1 ? CASE_CLOSED : CASE_UNKNOWN;
00696         }
00697         else
00698         {
00699             return switch1 ? CASE_PORTRAIT : CASE_LANDSCAPE;
00700         }
00701     }
00702 }
00703 
00704 void Zaurus::initHingeSensor()
00705 {
00706     if ( m_embedix ) return;
00707 
00708     m_hinge.setName( "/dev/input/event0" );
00709     if ( !m_hinge.open( IO_ReadOnly ) )
00710     {
00711         qWarning( "Zaurus::init() - Couldn't open /dev/input/event0 for read (%s)", strerror( errno ) );
00712         return;
00713     }
00714 
00715     QSocketNotifier* sn = new QSocketNotifier( m_hinge.handle(), QSocketNotifier::Read, this );
00716     QObject::connect( sn, SIGNAL(activated(int)), this, SLOT(hingeSensorTriggered()) );
00717 
00718     qDebug( "Zaurus::init() - Hinge Sensor Initialization successfully completed" );
00719 }
00720 
00721 void Zaurus::hingeSensorTriggered()
00722 {
00723     qDebug( "Zaurus::hingeSensorTriggered() - got event" );
00724     struct input_event e;
00725     if ( ::read( m_hinge.handle(), &e, sizeof e ) > 0 )
00726     {
00727         qDebug( "Zaurus::hingeSensorTriggered() - event has type %d, code %d, value %d", e.type, e.code, e.value );
00728         if ( e.type != EV_SW ) return;
00729         if ( readHingeSensor() != CASE_UNKNOWN )
00730         {
00731             qDebug( "Zaurus::hingeSensorTriggered() - got valid switch event, calling rotateDefault()" );
00732             QCopChannel::send( "QPE/Rotation", "rotateDefault()" );
00733         }
00734     }
00735 }
00736 
00737 void Zaurus::systemMessage( const QCString &msg, const QByteArray & )
00738 {
00739     if ( msg == "deviceButtonMappingChanged()" ) {
00740         reloadButtonMapping();
00741     }
00742 }
00743 
00744 /*
00745  * Take code from iPAQ device.
00746  * That way we switch the cursor directions depending on status of hinge sensor, eg. hardware direction.
00747  * I hope that is ok - Alwin
00748  */
00749 bool Zaurus::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
00750 {
00751     int newkeycode = keycode;
00752 
00753     if ( !hasHingeSensor() ) return false;
00754 
00755     /* map cursor keys depending on the hinge status */
00756     switch ( keycode ) {
00757         // Rotate cursor keys
00758         case Key_Left :
00759         case Key_Right:
00760         case Key_Up   :
00761         case Key_Down :
00762         {
00763             if (rotation()==Rot90) {
00764                 newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4;
00765             }
00766         }
00767         break;
00768 
00769     }
00770     if (newkeycode!=keycode) {
00771         if ( newkeycode != Key_unknown ) {
00772             QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
00773         }
00774         return true;
00775     }
00776     return false;
00777 }
00778 
00779 bool Zaurus::suspend() {
00780     if ( !isQWS( ) ) // only qwsserver is allowed to suspend
00781         return false;
00782 
00783     bool res = false;
00784     QCopChannel::send( "QPE/System", "aboutToSuspend()" );
00785 
00786     struct timeval tvs, tvn;
00787     ::gettimeofday ( &tvs, 0 );
00788 
00789     ::sync(); // flush fs caches
00790     res = ( ::system ( "apm --suspend" ) == 0 );
00791 
00792     // This is needed because some apm implementations are asynchronous and we
00793     // can not be sure when exactly the device is really suspended
00794     // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
00795     // on non embedix eg. 2.6 kernel line apm is synchronous so we don't need it here.
00796 
00797     if ( res && m_embedix) {
00798         do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
00799             ::usleep ( 200 * 1000 );
00800             ::gettimeofday ( &tvn, 0 );
00801         } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < m_timeOut );
00802     }
00803 
00804     QCopChannel::send( "QPE/System", "returnFromSuspend()" );
00805 
00806     return res;
00807 }

Generated on Sat Nov 5 16:16:06 2005 for OPIE by  doxygen 1.4.2