summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/device/odevice.cpp
Unidiff
Diffstat (limited to 'libopie2/opiecore/device/odevice.cpp') (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opiecore/device/odevice.cpp623
1 files changed, 623 insertions, 0 deletions
diff --git a/libopie2/opiecore/device/odevice.cpp b/libopie2/opiecore/device/odevice.cpp
new file mode 100644
index 0000000..0f88c3c
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice.cpp
@@ -0,0 +1,623 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) The Opie Team <opie-devel@handhelds.org>
4 =.
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; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
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.h"
31
32/* QT */
33#include <qapplication.h>
34#include <qfile.h>
35#include <qtextstream.h>
36#include <qwindowsystem_qws.h>
37
38/* OPIE */
39#include <qpe/config.h>
40#include <qpe/resource.h>
41#include <qpe/sound.h>
42#include <qpe/qcopenvelope_qws.h>
43
44/* STD */
45#include <fcntl.h>
46#include <math.h>
47#include <stdlib.h>
48#include <signal.h>
49#include <sys/ioctl.h>
50#include <sys/time.h>
51#include <unistd.h>
52#ifndef QT_NO_SOUND
53#include <linux/soundcard.h>
54#endif
55
56#ifndef ARRAY_SIZE
57#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
58#endif
59
60// _IO and friends are only defined in kernel headers ...
61
62#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
63
64#define OD_IO(type,number) OD_IOC(0,type,number,0)
65#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
66#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
67#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
68
69using namespace Opie;
70
71class iPAQ;
72class Zaurus;
73class SIMpad;
74class Ramses;
75class Jornada;
76
77ODevice *ODevice::inst()
78{
79 static ODevice *dev = 0;
80
81 // rewrite this to only use /proc/devinfo or so
82
83 /*
84 if ( !dev ) {
85 if ( QFile::exists ( "/proc/hal/model" ))
86 dev = new iPAQ();
87 else if ( Zaurus::isZaurus() )
88 dev = new Zaurus();
89 else if ( QFile::exists ( "/proc/ucb1x00" ) && QFile::exists ( "/proc/cs3" ))
90 dev = new SIMpad();
91 else if ( QFile::exists ( "/proc/sys/board/name" ))
92 dev = new Ramses();
93 else if ( Yopy::isYopy() )
94 dev = new Yopy();
95 else if ( Jornada::isJornada() )
96 dev = new Jornada();
97 else
98 dev = new ODevice();
99 dev->init();
100 }
101 */
102 return dev;
103}
104
105ODevice::ODevice()
106{
107 d = new ODeviceData;
108
109 d->m_modelstr = "Unknown";
110 d->m_model = Model_Unknown;
111 d->m_vendorstr = "Unknown";
112 d->m_vendor = Vendor_Unknown;
113 d->m_systemstr = "Unknown";
114 d->m_system = System_Unknown;
115 d->m_sysverstr = "0.0";
116 d->m_rotation = Rot0;
117 d->m_direction = CW;
118
119 d->m_holdtime = 1000; // 1000ms
120 d->m_buttons = 0;
121 d->m_cpu_frequencies = new QStrList;
122}
123
124void ODevice::systemMessage ( const QCString &msg, const QByteArray & )
125{
126 if ( msg == "deviceButtonMappingChanged()" ) {
127 reloadButtonMapping();
128 }
129}
130
131void ODevice::init()
132{
133}
134
135/**
136* This method initialises the button mapping
137*/
138void ODevice::initButtons()
139{
140 if ( d->m_buttons )
141 return;
142
143 qDebug ( "init Buttons" );
144 d->m_buttons = new QValueList <ODeviceButton>;
145
146 reloadButtonMapping();
147
148 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
149 connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
150}
151
152ODevice::~ODevice()
153{
154// we leak m_devicebuttons and m_cpu_frequency
155// but it's a singleton and it is not so importantant
156// -zecke
157 delete d;
158}
159
160bool ODevice::setSoftSuspend ( bool /*soft*/ )
161{
162 return false;
163}
164
165//#include <linux/apm_bios.h>
166
167#define APM_IOC_SUSPEND OD_IO( 'A', 2 )
168
169/**
170* This method will try to suspend the device
171* It only works if the user is the QWS Server and the apm application
172* is installed.
173* It tries to suspend and then waits some time cause some distributions
174* do have asynchronus apm implementations.
175* This method will either fail and return false or it'll suspend the
176* device and return once the device got woken up
177*
178* @return if the device got suspended
179*/
180bool ODevice::suspend()
181{
182 qDebug("ODevice::suspend");
183 if ( !isQWS( ) ) // only qwsserver is allowed to suspend
184 return false;
185
186 if ( d->m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
187 return false;
188
189 bool res = false;
190
191 struct timeval tvs, tvn;
192 ::gettimeofday ( &tvs, 0 );
193
194 ::sync(); // flush fs caches
195 res = ( ::system ( "apm --suspend" ) == 0 );
196
197 // This is needed because the iPAQ apm implementation is asynchronous and we
198 // can not be sure when exactly the device is really suspended
199 // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
200
201 if ( res ) {
202 do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
203 ::usleep ( 200 * 1000 );
204 ::gettimeofday ( &tvn, 0 );
205 } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 1500 );
206 }
207
208 return res;
209}
210
211//#include <linux/fb.h> better not rely on kernel headers in userspace ...
212
213#define FBIOBLANK OD_IO( 'F', 0x11 ) // 0x4611
214
215/* VESA Blanking Levels */
216#define VESA_NO_BLANKING 0
217#define VESA_VSYNC_SUSPEND 1
218#define VESA_HSYNC_SUSPEND 2
219#define VESA_POWERDOWN 3
220
221/**
222* This sets the display on or off
223*/
224bool ODevice::setDisplayStatus ( bool on )
225{
226 qDebug("ODevice::setDisplayStatus(%d)", on);
227
228 if ( d->m_model == Model_Unknown )
229 return false;
230
231 bool res = false;
232 int fd;
233
234 if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) {
235 res = ( ::ioctl ( fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN ) == 0 );
236 ::close ( fd );
237 }
238 return res;
239}
240
241/**
242* This sets the display brightness
243*
244* @param p The brightness to be set on a scale from 0 to 255
245* @return success or failure
246*/
247bool ODevice::setDisplayBrightness ( int p)
248{
249 Q_UNUSED( p )
250 return false;
251}
252
253/**
254* @return returns the number of steppings on the brightness slider
255* in the Light-'n-Power settings.
256*/
257int ODevice::displayBrightnessResolution() const
258{
259 return 16;
260}
261
262/**
263* This sets the display contrast
264* @param p The contrast to be set on a scale from 0 to 255
265* @return success or failure
266*/
267bool ODevice::setDisplayContrast ( int p)
268{
269 Q_UNUSED( p )
270 return false;
271}
272
273/**
274* @return return the max value for the brightness settings slider
275* or 0 if the device doesn't support setting of a contrast
276*/
277int ODevice::displayContrastResolution() const
278{
279 return 0;
280}
281
282/**
283* This returns the vendor as string
284* @return Vendor as QString
285*/
286QString ODevice::vendorString() const
287{
288 return d->m_vendorstr;
289}
290
291/**
292* This returns the vendor as one of the values of OVendor
293* @return OVendor
294*/
295OVendor ODevice::vendor() const
296{
297 return d->m_vendor;
298}
299
300/**
301* This returns the model as a string
302* @return A string representing the model
303*/
304QString ODevice::modelString() const
305{
306 return d->m_modelstr;
307}
308
309/**
310* This does return the OModel used
311*/
312OModel ODevice::model() const
313{
314 return d->m_model;
315}
316
317/**
318* This does return the systen name
319*/
320QString ODevice::systemString() const
321{
322 return d->m_systemstr;
323}
324
325/**
326* Return System as OSystem value
327*/
328OSystem ODevice::system() const
329{
330 return d->m_system;
331}
332
333/**
334* @return the version string of the base system
335*/
336QString ODevice::systemVersionString() const
337{
338 return d->m_sysverstr;
339}
340
341/**
342* @return the current Transformation
343*/
344Transformation ODevice::rotation() const
345{
346 return d->m_rotation;
347}
348
349/**
350* @return the current rotation direction
351*/
352ODirection ODevice::direction() const
353{
354 return d->m_direction;
355}
356
357/**
358* This plays an alarmSound
359*/
360void ODevice::alarmSound()
361{
362#ifndef QT_NO_SOUND
363 static Sound snd ( "alarm" );
364
365 if ( snd. isFinished())
366 snd. play();
367#endif
368}
369
370/**
371* This plays a key sound
372*/
373void ODevice::keySound()
374{
375#ifndef QT_NO_SOUND
376 static Sound snd ( "keysound" );
377
378 if ( snd. isFinished())
379 snd. play();
380#endif
381}
382
383/**
384* This plays a touch sound
385*/
386void ODevice::touchSound()
387{
388#ifndef QT_NO_SOUND
389 static Sound snd ( "touchsound" );
390
391 if ( snd. isFinished())
392 snd. play();
393#endif
394}
395
396/**
397* This method will return a list of leds
398* available on this device
399* @return a list of LEDs.
400*/
401QValueList <OLed> ODevice::ledList() const
402{
403 return QValueList <OLed>();
404}
405
406/**
407* This does return the state of the LEDs
408*/
409QValueList <OLedState> ODevice::ledStateList ( OLed /*which*/ ) const
410{
411 return QValueList <OLedState>();
412}
413
414/**
415* @return the state for a given OLed
416*/
417OLedState ODevice::ledState ( OLed /*which*/ ) const
418{
419 return Led_Off;
420}
421
422/**
423* Set the state for a LED
424* @param which Which OLed to use
425* @param st The state to set
426* @return success or failure
427*/
428bool ODevice::setLedState ( OLed which, OLedState st )
429{
430 Q_UNUSED( which )
431 Q_UNUSED( st )
432 return false;
433}
434
435/**
436* @return if the device has a light sensor
437*/
438bool ODevice::hasLightSensor() const
439{
440 return false;
441}
442
443/**
444* @return a value from the light sensor
445*/
446int ODevice::readLightSensor()
447{
448 return -1;
449}
450
451/**
452* @return the light sensor resolution
453*/
454int ODevice::lightSensorResolution() const
455{
456 return 0;
457}
458
459/**
460* @return if the device has a hinge sensor
461*/
462bool ODevice::hasHingeSensor() const
463{
464 return false;
465}
466
467/**
468* @return a value from the hinge sensor
469*/
470OHingeStatus ODevice::readHingeSensor()
471{
472 return CASE_UNKNOWN;
473}
474
475/**
476* @return a list with CPU frequencies supported by the hardware
477*/
478const QStrList &ODevice::allowedCpuFrequencies() const
479{
480 return *d->m_cpu_frequencies;
481}
482
483
484/**
485* Set desired CPU frequency
486*
487* @param index index into d->m_cpu_frequencies of the frequency to be set
488*/
489bool ODevice::setCurrentCpuFrequency(uint index)
490{
491 if (index >= d->m_cpu_frequencies->count())
492 return false;
493
494 char *freq = d->m_cpu_frequencies->at(index);
495 qWarning("set freq to %s", freq);
496
497 int fd;
498
499 if ((fd = ::open("/proc/sys/cpu/0/speed", O_WRONLY)) >= 0) {
500 char writeCommand[50];
501 const int count = sprintf(writeCommand, "%s\n", freq);
502 int res = (::write(fd, writeCommand, count) != -1);
503 ::close(fd);
504 return res;
505 }
506
507 return false;
508}
509
510
511/**
512* @return a list of hardware buttons
513*/
514const QValueList <ODeviceButton> &ODevice::buttons()
515{
516 initButtons();
517
518 return *d->m_buttons;
519}
520
521/**
522* @return The amount of time that would count as a hold
523*/
524uint ODevice::buttonHoldTime() const
525{
526 return d->m_holdtime;
527}
528
529/**
530* This method return a ODeviceButton for a key code
531* or 0 if no special hardware button is available for the device
532*
533* @return The devicebutton or 0l
534* @see ODeviceButton
535*/
536const ODeviceButton *ODevice::buttonForKeycode ( ushort code )
537{
538 initButtons();
539
540 for ( QValueListConstIterator<ODeviceButton> it = d->m_buttons->begin(); it != d->m_buttons->end(); ++it ) {
541 if ( (*it). keycode() == code )
542 return &(*it);
543 }
544 return 0;
545}
546
547void ODevice::reloadButtonMapping()
548{
549 initButtons();
550
551 Config cfg ( "ButtonSettings" );
552
553 for ( uint i = 0; i < d->m_buttons->count(); i++ ) {
554 ODeviceButton &b = ( *d->m_buttons ) [i];
555 QString group = "Button" + QString::number ( i );
556
557 QCString pch, hch;
558 QCString pm, hm;
559 QByteArray pdata, hdata;
560
561 if ( cfg. hasGroup ( group )) {
562 cfg. setGroup ( group );
563 pch = cfg. readEntry ( "PressedActionChannel" ). latin1();
564 pm = cfg. readEntry ( "PressedActionMessage" ). latin1();
565 // pdata = decodeBase64 ( buttonFile. readEntry ( "PressedActionArgs" ));
566
567 hch = cfg. readEntry ( "HeldActionChannel" ). latin1();
568 hm = cfg. readEntry ( "HeldActionMessage" ). latin1();
569 // hdata = decodeBase64 ( buttonFile. readEntry ( "HeldActionArgs" ));
570 }
571
572 b. setPressedAction ( OQCopMessage ( pch, pm, pdata ));
573
574 b. setHeldAction ( OQCopMessage ( hch, hm, hdata ));
575 }
576}
577
578void ODevice::remapPressedAction ( int button, const OQCopMessage &action )
579{
580 initButtons();
581
582 QString mb_chan;
583
584 if ( button >= (int) d->m_buttons->count())
585 return;
586
587 ODeviceButton &b = ( *d->m_buttons ) [button];
588 b. setPressedAction ( action );
589
590 mb_chan=b. pressedAction(). channel();
591
592 Config buttonFile ( "ButtonSettings" );
593 buttonFile. setGroup ( "Button" + QString::number ( button ));
594 buttonFile. writeEntry ( "PressedActionChannel", (const char*) mb_chan);
595 buttonFile. writeEntry ( "PressedActionMessage", (const char*) b. pressedAction(). message());
596
597 //buttonFile. writeEntry ( "PressedActionArgs", encodeBase64 ( b. pressedAction(). data()));
598
599 QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
600}
601
602void ODevice::remapHeldAction ( int button, const OQCopMessage &action )
603{
604 initButtons();
605
606 if ( button >= (int) d->m_buttons->count())
607 return;
608
609 ODeviceButton &b = ( *d->m_buttons ) [button];
610 b. setHeldAction ( action );
611
612 Config buttonFile ( "ButtonSettings" );
613 buttonFile. setGroup ( "Button" + QString::number ( button ));
614 buttonFile. writeEntry ( "HeldActionChannel", (const char *) b. heldAction(). channel());
615 buttonFile. writeEntry ( "HeldActionMessage", (const char *) b. heldAction(). message());
616
617 //buttonFile. writeEntry ( "HeldActionArgs", decodeBase64 ( b. heldAction(). data()));
618
619 QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
620}
621void ODevice::virtual_hook(int, void* ){
622
623}