summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/device/odevice_htc.cpp721
1 files changed, 721 insertions, 0 deletions
diff --git a/libopie2/opiecore/device/odevice_htc.cpp b/libopie2/opiecore/device/odevice_htc.cpp
new file mode 100644
index 0000000..a40308d
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_htc.cpp
@@ -0,0 +1,721 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2002-2005 The Opie Team <opie-devel@handhelds.org>
4 =. Copyright (C) 2002-2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; version 2 of the License.
12     ._= =}       :
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28*/
29
30#include "odevice_htc.h"
31
32/* OPIE */
33#include <opie2/oinputsystem.h>
34#include <opie2/oresource.h>
35
36#include <qpe/config.h>
37#include <qpe/sound.h>
38
39/* QT */
40#include <qapplication.h>
41#include <qfile.h>
42#include <qtextstream.h>
43#include <qwindowsystem_qws.h>
44#include <qcopchannel_qws.h>
45
46/* STD */
47#include <string.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <math.h>
51#include <stdlib.h>
52#include <signal.h>
53#include <sys/ioctl.h>
54#include <sys/time.h>
55#include <unistd.h>
56#ifndef QT_NO_SOUND
57#include <linux/soundcard.h>
58#endif
59
60using namespace Opie::Core;
61using namespace Opie::Core::Internal;
62
63struct htc_button htc_buttons [] = {
64 { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
65 "devicebuttons/z_calendar",
66 "datebook", "nextView()",
67 "today", "raise()" },
68 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
69 "devicebuttons/z_contact",
70 "addressbook", "raise()",
71 "addressbook", "beamBusinessCard()" },
72 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
73 "devicebuttons/z_home",
74 "QPE/Launcher", "home()",
75 "buttonsettings", "raise()" },
76 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
77 "devicebuttons/z_menu",
78 "QPE/TaskBar", "toggleMenu()",
79 "QPE/TaskBar", "toggleStartMenu()" },
80 { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
81 "devicebuttons/z_mail",
82 "opiemail", "raise()",
83 "opiemail", "newMail()" },
84};
85
86struct htc_button htc_buttons_universal [] = {
87 { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
88 "devicebuttons/z_calendar",
89 "datebook", "nextView()",
90 "today", "raise()" },
91 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
92 "devicebuttons/z_contact",
93 "addressbook", "raise()",
94 "addressbook", "beamBusinessCard()" },
95 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
96 "devicebuttons/z_home",
97 "QPE/Launcher", "home()",
98 "buttonsettings", "raise()" },
99 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
100 "devicebuttons/z_menu",
101 "QPE/TaskBar", "toggleMenu()",
102 "QPE/TaskBar", "toggleStartMenu()" },
103 { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
104 "devicebuttons/z_mail",
105 "opiemail", "raise()",
106 "opiemail", "newMail()" },
107
108 { Qt::Key_F15, QT_TRANSLATE_NOOP("Button", "Hinge1"),
109 "devicebuttons/z_hinge1",
110 "QPE/Rotation", "rotateDefault()",0},
111 { Qt::Key_F16, QT_TRANSLATE_NOOP("Button", "Hinge2"),
112 "devicebuttons/z_hinge2",
113 "QPE/Rotation", "rotateDefault()",0},
114 { Qt::Key_F17, QT_TRANSLATE_NOOP("Button", "Hinge3"),
115 "devicebuttons/z_hinge3",
116 "QPE/Rotation", "rotateDefault()",0},
117};
118
119struct htc_button htc_buttons_6000 [] = {
120 { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
121 "devicebuttons/z_calendar",
122 "datebook", "nextView()",
123 "today", "raise()" },
124 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
125 "devicebuttons/z_contact",
126 "addressbook", "raise()",
127 "addressbook", "beamBusinessCard()" },
128 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
129 "devicebuttons/z_home",
130 "QPE/Launcher", "home()",
131 "buttonsettings", "raise()" },
132 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
133 "devicebuttons/z_menu",
134 "QPE/TaskBar", "toggleMenu()",
135 "QPE/TaskBar", "toggleStartMenu()" },
136 { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
137 "devicebuttons/z_mail",
138 "opiemail", "raise()",
139 "opiemail", "newMail()" },
140 { Qt::Key_F15, QT_TRANSLATE_NOOP("Button", "Rotate Button"),
141 "devicebuttons/z_rotate",
142 0,
143 "QPE/Rotation", "rotateDefault()" },
144 { Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
145 "devicebuttons/z_hinge3",
146 "QPE/VMemo", "toggleRecord()",
147 "sound", "raise()" },
148};
149
150// FIXME This gets unnecessary complicated. We should think about splitting the HTC
151// class up into individual classes. We would need three classes
152//
153// HTC-Universal (PXA-model w/ 640x480 lcd, for Universal)
154
155void HTC::init(const QString& cpu_info)
156{
157 qDebug( "HTC::init()" );
158 // Set the time to wait until the system is really suspended
159 // the delta between apm --suspend and sleeping
160 setAPMTimeOut( 15000 );
161
162 // generic distribution code already scanned /etc/issue at that point -
163 // embedix releases contain "Embedix <version> | Linux for Embedded Devices"
164 if ( d->m_sysverstr.contains( "embedix", false ) )
165 {
166 d->m_vendorstr = "HTC";
167 d->m_vendor = Vendor_HTC;
168 d->m_systemstr = "OpenEmbedded";
169 d->m_system = System_OpenEmbedded;
170 m_embedix = true;
171 }
172 else
173 {
174 d->m_vendorstr = "Xanadux Team";
175 d->m_systemstr = "Familiar";
176 d->m_system = System_Familiar;
177 // sysver already gathered
178
179 // OpenHTC sometimes uses the 2.4 (embedix) kernel, check if this is one
180 FILE *uname = popen("uname -r", "r");
181 QFile f;
182 QString line;
183 if ( f.open(IO_ReadOnly, uname) ) {
184 QTextStream ts ( &f );
185 line = ts.readLine();
186 m_embedix = line.startsWith( "2.4." );
187 f.close();
188 }
189 pclose(uname);
190 }
191
192 // check the HTC model
193 QString model;
194 int loc = cpu_info.find( ":" );
195 if ( loc != -1 )
196 model = cpu_info.mid( loc+2 ).simplifyWhiteSpace();
197 else
198 model = cpu_info;
199
200 if ( model == "HTC Universal" ) {
201 d->m_model = Model_HTC_Universal;
202 d->m_modelstr = "HTC Universal";
203 } else {
204 d->m_model = Model_HTC_Universal;
205 d->m_modelstr = "Unknown HTC";
206 }
207
208 // set path to backlight device in kernel 2.6
209 switch ( d->m_model )
210 {
211 case Model_HTC_Universal:
212 default:
213// m_backlightdev = "/sys/class/backlight/corgi-bl/";
214 m_backlightdev = "/sys/class/backlight/pxafb/";
215 }
216
217 // set initial rotation
218 switch( d->m_model )
219 {
220 case Model_HTC_Universal:
221 initHingeSensor();
222 d->m_rotation = rotation();
223 d->m_direction = direction();
224 break;
225 default:
226 d->m_rotation = Rot270;
227 }
228
229 // set default qte driver
230 switch( d->m_model )
231 {
232 default:
233 d->m_qteDriver = "Transformed";
234 }
235
236 m_leds[0] = Led_Off;
237
238 if ( m_embedix )
239 qDebug( "HTC::init() - Using the 2.4 Embedix HAL on a %s", (const char*) d->m_modelstr );
240 else
241 qDebug( "HTC::init() - Using the 2.6 Xanadux HAL on a %s", (const char*) d->m_modelstr );
242}
243
244void HTC::initButtons()
245{
246 qDebug( "HTC::initButtons()" );
247 if ( d->m_buttons )
248 return;
249
250 d->m_buttons = new QValueList <ODeviceButton>;
251
252 struct htc_button * phtc_buttons;
253 int buttoncount;
254 switch ( d->m_model )
255 {
256 case Model_HTC_Universal:
257 if ( isQWS( ) )
258 {
259 addPreHandler(this);
260 }
261 phtc_buttons = htc_buttons_universal;
262 buttoncount = ARRAY_SIZE(htc_buttons_universal);
263 break;
264 default:
265 phtc_buttons = htc_buttons;
266 buttoncount = ARRAY_SIZE(htc_buttons);
267 break;
268 }
269
270 for ( int i = 0; i < buttoncount; i++ ) {
271 struct htc_button *zb = phtc_buttons + i;
272 ODeviceButton b;
273
274 b.setKeycode( zb->code );
275 b.setUserText( QObject::tr( "Button", zb->utext ));
276 b.setPixmap( OResource::loadPixmap( zb->pix ));
277 b.setFactoryPresetPressedAction( OQCopMessage( makeChannel ( zb->fpressedservice ), zb->fpressedaction ));
278 b.setFactoryPresetHeldAction( OQCopMessage( makeChannel ( zb->fheldservice ), zb->fheldaction ));
279 d->m_buttons->append( b );
280 }
281
282 reloadButtonMapping();
283}
284
285
286
287typedef struct sharp_led_status {
288 int which; /* select which LED status is wanted. */
289 int status; /* set new led status if you call SHARP_LED_SETSTATUS */
290} sharp_led_status;
291
292void HTC::buzzer( int sound )
293{
294#ifndef QT_NO_SOUND
295 Sound *snd = 0;
296
297 // All devices except SL5500 have a DSP device
298 if ( d->m_model == Model_HTC_Universal ) {
299
300 switch ( sound ){
301 case SHARP_BUZ_TOUCHSOUND: {
302 static Sound touch_sound("touchsound");
303 snd = &touch_sound;
304 }
305 break;
306 case SHARP_BUZ_KEYSOUND: {
307 static Sound key_sound( "keysound" );
308 snd = &key_sound;
309 }
310 break;
311 case SHARP_BUZ_SCHEDULE_ALARM:
312 default: {
313 static Sound alarm_sound("alarm");
314 snd = &alarm_sound;
315 }
316 break;
317 }
318 }
319
320 // If a soundname is defined, we expect that this device has
321 // sound capabilities.. Otherwise we expect to have the buzzer
322 // device..
323 if ( snd && snd->isFinished() ){
324 changeMixerForAlarm( 0, "/dev/sound/mixer", snd );
325 snd->play();
326 } else if( !snd ) {
327 int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK );
328
329 if ( fd >= 0 ) {
330 ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound );
331 ::close ( fd );
332 }
333
334 }
335#endif
336}
337
338
339void HTC::playAlarmSound()
340{
341 buzzer( SHARP_BUZ_SCHEDULE_ALARM );
342}
343
344void HTC::playTouchSound()
345{
346 buzzer( SHARP_BUZ_TOUCHSOUND );
347}
348
349void HTC::playKeySound()
350{
351 buzzer( SHARP_BUZ_KEYSOUND );
352}
353
354
355QValueList <OLed> HTC::ledList() const
356{
357 QValueList <OLed> vl;
358 vl << Led_Mail;
359 return vl;
360}
361
362QValueList <OLedState> HTC::ledStateList( OLed l ) const
363{
364 QValueList <OLedState> vl;
365
366 if ( l == Led_Mail )
367 vl << Led_Off << Led_On << Led_BlinkSlow;
368 return vl;
369}
370
371OLedState HTC::ledState( OLed which ) const
372{
373 if ( which == Led_Mail )
374 return m_leds [0];
375 else
376 return Led_Off;
377}
378
379bool HTC::setLedState( OLed which, OLedState st )
380{
381 // Currently not supported on non_embedix kernels
382 if (!m_embedix)
383 {
384 qDebug( "HTC::setLedState: ODevice handling for non-embedix kernels not yet implemented" );
385 return false;
386 }
387
388 static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK );
389
390 if ( which == Led_Mail ) {
391 if ( fd >= 0 ) {
392 struct sharp_led_status leds;
393 ::memset ( &leds, 0, sizeof( leds ));
394 leds. which = SHARP_LED_MAIL_EXISTS;
395 bool ok = true;
396
397 switch ( st ) {
398 case Led_Off : leds. status = LED_MAIL_NO_UNREAD_MAIL; break;
399 case Led_On : leds. status = LED_MAIL_NEWMAIL_EXISTS; break;
400 case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break;
401 default : ok = false;
402 }
403
404 if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) {
405 m_leds [0] = st;
406 return true;
407 }
408 }
409 }
410 return false;
411}
412
413int HTC::displayBrightnessResolution() const
414{
415/* MV */
416 return 16;
417
418 int res = 1;
419 if (m_embedix)
420 {
421 int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_RDWR|O_NONBLOCK );
422 if ( fd )
423 {
424 int value = ::ioctl( fd, SHARP_FL_IOCTL_GET_STEP, 0 );
425 ::close( fd );
426 return value ? value : res;
427 }
428 }
429 else
430 {
431 int fd = ::open( m_backlightdev + "max_brightness", O_RDONLY|O_NONBLOCK );
432 if ( fd )
433 {
434 char buf[100];
435 if ( ::read( fd, &buf[0], sizeof buf ) ) ::sscanf( &buf[0], "%d", &res );
436 ::close( fd );
437 }
438 }
439 return res;
440}
441
442bool HTC::setDisplayBrightness( int bright )
443{
444/* MV */
445 return false;
446
447 //qDebug( "HTC::setDisplayBrightness( %d )", bright );
448 bool res = false;
449
450 if ( bright > 255 ) bright = 255;
451 if ( bright < 0 ) bright = 0;
452
453 int numberOfSteps = displayBrightnessResolution();
454 int val = ( bright == 1 ) ? 1 : ( bright * numberOfSteps ) / 255;
455
456 if ( m_embedix )
457 {
458 int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_WRONLY|O_NONBLOCK );
459 if ( fd )
460 {
461 res = ( ::ioctl( fd, SHARP_FL_IOCTL_STEP_CONTRAST, val ) == 0 );
462 ::close( fd );
463 }
464 }
465 else
466 {
467 int fd = ::open( m_backlightdev + "brightness", O_WRONLY|O_NONBLOCK );
468 if ( fd )
469 {
470 char buf[100];
471 int len = ::snprintf( &buf[0], sizeof buf, "%d", val );
472 res = ( ::write( fd, &buf[0], len ) == 0 );
473 ::close( fd );
474 }
475 }
476 return res;
477}
478
479bool HTC::setDisplayStatus( bool on )
480{
481/* MV */
482 return false;
483
484 bool res = false;
485 if ( m_embedix )
486 {
487 int fd = ::open( SHARP_FL_IOCTL_DEVICE, O_WRONLY|O_NONBLOCK );
488 if ( fd )
489 {
490 int ioctlnum = on ? SHARP_FL_IOCTL_ON : SHARP_FL_IOCTL_OFF;
491 res = ( ::ioctl ( fd, ioctlnum, 0 ) == 0 );
492 ::close ( fd );
493 }
494 }
495 else
496 {
497 int fd = ::open( m_backlightdev + "power", O_WRONLY|O_NONBLOCK );
498 if ( fd )
499 {
500 char buf[10];
501 buf[0] = on ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
502 buf[1] = '\0';
503 res = ( ::write( fd, &buf[0], 2 ) == 0 );
504 ::close( fd );
505 }
506 }
507 return res;
508}
509
510Transformation HTC::rotation() const
511{
512 qDebug( "HTC::rotation()" );
513 Transformation rot;
514
515 switch ( d->m_model ) {
516 case Model_HTC_Universal:
517 {
518 OHingeStatus hs = readHingeSensor();
519 qDebug( "HTC::rotation() - hinge sensor = %d", (int) hs );
520 if ( hs == CASE_PORTRAIT ) rot = Rot0;
521 else if ( hs == CASE_UNKNOWN ) rot = Rot270;
522 else rot = Rot270;
523 }
524 break;
525 }
526
527 qDebug( "HTC::rotation() - returning '%d'", rot );
528 return rot;
529}
530ODirection HTC::direction() const
531{
532 ODirection dir;
533
534 switch ( d->m_model ) {
535 case Model_HTC_Universal: {
536 OHingeStatus hs = readHingeSensor();
537 if ( hs == CASE_PORTRAIT ) dir = CCW;
538 else if ( hs == CASE_UNKNOWN ) dir = CCW;
539 else dir = CW;
540 }
541 break;
542 default: dir = d->m_direction;
543 break;
544 }
545 return dir;
546
547}
548
549bool HTC::hasHingeSensor() const
550{
551 return d->m_model == Model_HTC_Universal;
552}
553
554OHingeStatus HTC::readHingeSensor() const
555{
556 if (m_embedix)
557 {
558 int handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
559 if (handle == -1)
560 {
561 qWarning("HTC::readHingeSensor() - failed (%s)", "unknown reason" ); //FIXME: use strerror
562 return CASE_UNKNOWN;
563 }
564 else
565 {
566 int retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
567 ::close (handle);
568 if ( retval == CASE_CLOSED || retval == CASE_PORTRAIT || retval == CASE_LANDSCAPE )
569 {
570 qDebug( "HTC::readHingeSensor() - result = %d", retval );
571 return static_cast<OHingeStatus>( retval );
572 }
573 else
574 {
575 qWarning("HTC::readHingeSensor() - couldn't compute hinge status!" );
576 return CASE_UNKNOWN;
577 }
578 }
579 }
580 else
581 {
582 /*
583 * The HTC Universal keyboard is event source 1 in kernel 2.6.
584 * Hinge status is reported via Input System Switchs 0 and 1 like that:
585 *
586 * -------------------------
587 * | SW0 | SW1 | CASE |
588 * |-----|-----|-----------|
589 * | 0 0 Unknown |
590 * | 1 0 Portrait |
591 * | 0 1 Closed |
592 * | 1 1 Landscape |
593 * -------------------------
594 */
595 OInputDevice* keyboard = OInputSystem::instance()->device( "event1" );
596 bool switch0 = true;
597 bool switch1 = false;
598 if ( keyboard )
599 {
600 switch0 = keyboard->isHeld( OInputDevice::Switch0 );
601 switch1 = keyboard->isHeld( OInputDevice::Switch1 );
602 }
603 if ( switch0 )
604 {
605 return switch1 ? CASE_LANDSCAPE : CASE_PORTRAIT;
606 }
607 else
608 {
609 return switch1 ? CASE_CLOSED : CASE_UNKNOWN;
610 }
611 }
612}
613
614void HTC::initHingeSensor()
615{
616 if ( m_embedix ) return;
617
618 m_hinge.setName( "/dev/input/event1" );
619 if ( !m_hinge.open( IO_ReadOnly ) )
620 {
621 qWarning( "HTC::init() - Couldn't open /dev/input/event1 for read (%s)", strerror( errno ) );
622 return;
623 }
624
625 QSocketNotifier* sn = new QSocketNotifier( m_hinge.handle(), QSocketNotifier::Read, this );
626 QObject::connect( sn, SIGNAL(activated(int)), this, SLOT(hingeSensorTriggered()) );
627
628 qDebug( "HTC::init() - Hinge Sensor Initialization successfully completed" );
629}
630
631void HTC::hingeSensorTriggered()
632{
633 qDebug( "HTC::hingeSensorTriggered() - got event" );
634 struct input_event e;
635 if ( ::read( m_hinge.handle(), &e, sizeof e ) > 0 )
636 {
637 qDebug( "HTC::hingeSensorTriggered() - event has type %d, code %d, value %d", e.type, e.code, e.value );
638 if ( e.type != EV_SW ) return;
639 if ( readHingeSensor() != CASE_UNKNOWN )
640 {
641 qDebug( "HTC::hingeSensorTriggered() - got valid switch event, calling rotateDefault()" );
642 QCopChannel::send( "QPE/Rotation", "rotateDefault()" );
643 }
644 }
645}
646
647void HTC::systemMessage( const QCString &msg, const QByteArray & )
648{
649 if ( msg == "deviceButtonMappingChanged()" ) {
650 reloadButtonMapping();
651 }
652}
653
654/*
655 * Take code from iPAQ device.
656 * That way we switch the cursor directions depending on status of hinge sensor, eg. hardware direction.
657 * I hope that is ok - Alwin
658 */
659bool HTC::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
660{
661 int newkeycode = keycode;
662
663 if ( !hasHingeSensor() ) return false;
664
665 /* map cursor keys depending on the hinge status */
666 switch ( keycode ) {
667 // Rotate cursor keys
668 case Key_Left :
669 case Key_Right:
670 case Key_Up :
671 case Key_Down :
672 {
673 if (rotation()==Rot90) {
674 newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4;
675 }
676 }
677 break;
678
679 }
680 if (newkeycode!=keycode) {
681 if ( newkeycode != Key_unknown ) {
682 QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
683 }
684 return true;
685 }
686 return false;
687}
688
689bool HTC::suspend() {
690
691/* MV */
692 return false;
693
694 if ( !isQWS( ) ) // only qwsserver is allowed to suspend
695 return false;
696
697 bool res = false;
698 QCopChannel::send( "QPE/System", "aboutToSuspend()" );
699
700 struct timeval tvs, tvn;
701 ::gettimeofday ( &tvs, 0 );
702
703 ::sync(); // flush fs caches
704 res = ( ::system ( "apm --suspend" ) == 0 );
705
706 // This is needed because some apm implementations are asynchronous and we
707 // can not be sure when exactly the device is really suspended
708 // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
709 // on non embedix eg. 2.6 kernel line apm is synchronous so we don't need it here.
710
711 if ( res && m_embedix) {
712 do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
713 ::usleep ( 200 * 1000 );
714 ::gettimeofday ( &tvn, 0 );
715 } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < m_timeOut );
716 }
717
718 QCopChannel::send( "QPE/System", "returnFromSuspend()" );
719
720 return res;
721}