summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/device/odevice_ipaq.cpp
authormickeyl <mickeyl>2004-01-13 15:21:40 (UTC)
committer mickeyl <mickeyl>2004-01-13 15:21:40 (UTC)
commitaf79bda4c7e51f46abe67124f9c06126eaebb59d (patch) (unidiff)
tree4e9ad77ec4b2bb3d66ac6553d0a225b0b18f2140 /libopie2/opiecore/device/odevice_ipaq.cpp
parent24eb97ec5cda3d72c3541fd120568b8d937025f8 (diff)
downloadopie-af79bda4c7e51f46abe67124f9c06126eaebb59d.zip
opie-af79bda4c7e51f46abe67124f9c06126eaebb59d.tar.gz
opie-af79bda4c7e51f46abe67124f9c06126eaebb59d.tar.bz2
- split odevice into dedicated files and classes, it has getting much too large
- merge odevice into libopie2 - merge oprocctrl and oprocess into libopie2
Diffstat (limited to 'libopie2/opiecore/device/odevice_ipaq.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/device/odevice_ipaq.cpp524
1 files changed, 524 insertions, 0 deletions
diff --git a/libopie2/opiecore/device/odevice_ipaq.cpp b/libopie2/opiecore/device/odevice_ipaq.cpp
new file mode 100644
index 0000000..d928806
--- a/dev/null
+++ b/libopie2/opiecore/device/odevice_ipaq.cpp
@@ -0,0 +1,524 @@
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
69typedef struct {
70 unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */
71 unsigned char TotalTime; /* Units of 5 seconds */
72 unsigned char OnTime; /* units of 100m/s */
73 unsigned char OffTime; /* units of 100m/s */
74} LED_IN;
75
76typedef struct {
77 unsigned char mode;
78 unsigned char pwr;
79 unsigned char brightness;
80} FLITE_IN;
81
82#define LED_ON OD_IOW( 'f', 5, LED_IN )
83#define FLITE_ON OD_IOW( 'f', 7, FLITE_IN )
84
85using namespace Opie;
86
87class iPAQ : public ODevice, public QWSServer::KeyboardFilter
88{
89
90 protected:
91 virtual void init();
92 virtual void initButtons();
93
94 public:
95 virtual bool setSoftSuspend( bool soft );
96
97 virtual bool setDisplayBrightness( int b );
98 virtual int displayBrightnessResolution() const;
99
100 virtual void alarmSound();
101
102 virtual QValueList <OLed> ledList() const;
103 virtual QValueList <OLedState> ledStateList( OLed led ) const;
104 virtual OLedState ledState( OLed led ) const;
105 virtual bool setLedState( OLed led, OLedState st );
106
107 virtual bool hasLightSensor() const;
108 virtual int readLightSensor();
109 virtual int lightSensorResolution() const;
110
111 protected:
112 virtual bool filter( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
113 virtual void timerEvent( QTimerEvent *te );
114
115 int m_power_timer;
116
117 OLedState m_leds [2];
118};
119
120struct i_button {
121 uint model;
122 Qt::Key code;
123 char *utext;
124 char *pix;
125 char *fpressedservice;
126 char *fpressedaction;
127 char *fheldservice;
128 char *fheldaction;
129} ipaq_buttons [] = {
130 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
131 Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
132 "devicebuttons/ipaq_calendar",
133 "datebook", "nextView()",
134 "today", "raise()" },
135 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
136 Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
137 "devicebuttons/ipaq_contact",
138 "addressbook", "raise()",
139 "addressbook", "beamBusinessCard()" },
140 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx,
141 Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
142 "devicebuttons/ipaq_menu",
143 "QPE/TaskBar", "toggleMenu()",
144 "QPE/TaskBar", "toggleStartMenu()" },
145 { Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
146 Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
147 "devicebuttons/ipaq_mail",
148 "mail", "raise()",
149 "mail", "newMail()" },
150 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
151 Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
152 "devicebuttons/ipaq_home",
153 "QPE/Launcher", "home()",
154 "buttonsettings", "raise()" },
155 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
156 Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
157 "devicebuttons/ipaq_record",
158 "QPE/VMemo", "toggleRecord()",
159 "sound", "raise()" },
160};
161
162void iPAQ::init()
163{
164 d->m_vendorstr = "HP";
165 d->m_vendor = Vendor_HP;
166
167 QFile f ( "/proc/hal/model" );
168
169 if ( f. open ( IO_ReadOnly )) {
170 QTextStream ts ( &f );
171
172 d->m_modelstr = "H" + ts. readLine();
173
174 if ( d->m_modelstr == "H3100" )
175 d->m_model = Model_iPAQ_H31xx;
176 else if ( d->m_modelstr == "H3600" )
177 d->m_model = Model_iPAQ_H36xx;
178 else if ( d->m_modelstr == "H3700" )
179 d->m_model = Model_iPAQ_H37xx;
180 else if ( d->m_modelstr == "H3800" )
181 d->m_model = Model_iPAQ_H38xx;
182 else if ( d->m_modelstr == "H3900" )
183 d->m_model = Model_iPAQ_H39xx;
184 else if ( d->m_modelstr == "H5400" )
185 d->m_model = Model_iPAQ_H5xxx;
186 else
187 d->m_model = Model_Unknown;
188
189 f. close();
190 }
191
192 switch ( d->m_model ) {
193 case Model_iPAQ_H31xx:
194 case Model_iPAQ_H38xx:
195 d->m_rotation = Rot90;
196 break;
197 case Model_iPAQ_H36xx:
198 case Model_iPAQ_H37xx:
199 case Model_iPAQ_H39xx:
200
201 default:
202 d->m_rotation = Rot270;
203 break;
204 case Model_iPAQ_H5xxx:
205 d->m_rotation = Rot0;
206 }
207
208 f. setName ( "/etc/familiar-version" );
209 if ( f. open ( IO_ReadOnly )) {
210 d->m_systemstr = "Familiar";
211 d->m_system = System_Familiar;
212
213 QTextStream ts ( &f );
214 d->m_sysverstr = ts. readLine(). mid ( 10 );
215
216 f. close();
217 } else {
218 f. setName ( "/etc/oz_version" );
219
220 if ( f. open ( IO_ReadOnly )) {
221 d->m_systemstr = "OpenEmbedded/iPaq";
222 d->m_system = System_Familiar;
223
224 QTextStream ts ( &f );
225 ts.setDevice ( &f );
226 d->m_sysverstr = ts. readLine();
227 f. close();
228 }
229 }
230
231 m_leds [0] = m_leds [1] = Led_Off;
232
233 m_power_timer = 0;
234
235}
236
237void iPAQ::initButtons()
238{
239 if ( d->m_buttons )
240 return;
241
242 if ( isQWS( ) )
243 QWSServer::setKeyboardFilter ( this );
244
245 d->m_buttons = new QValueList <ODeviceButton>;
246
247 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
248 i_button *ib = ipaq_buttons + i;
249 ODeviceButton b;
250
251 if (( ib->model & d->m_model ) == d->m_model ) {
252 b. setKeycode ( ib->code );
253 b. setUserText ( QObject::tr ( "Button", ib->utext ));
254 b. setPixmap ( Resource::loadPixmap ( ib->pix ));
255 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib->fpressedservice ), ib->fpressedaction ));
256 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib->fheldservice ), ib->fheldaction ));
257
258 d->m_buttons->append ( b );
259 }
260 }
261 reloadButtonMapping();
262
263 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
264 connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & )));
265}
266
267QValueList <OLed> iPAQ::ledList() const
268{
269 QValueList <OLed> vl;
270 vl << Led_Power;
271
272 if ( d->m_model == Model_iPAQ_H38xx )
273 vl << Led_BlueTooth;
274 return vl;
275}
276
277QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const
278{
279 QValueList <OLedState> vl;
280
281 if ( l == Led_Power )
282 vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast;
283 else if ( l == Led_BlueTooth && d->m_model == Model_iPAQ_H38xx )
284 vl << Led_Off; // << Led_On << ???
285
286 return vl;
287}
288
289OLedState iPAQ::ledState ( OLed l ) const
290{
291 switch ( l ) {
292 case Led_Power:
293 return m_leds [0];
294 case Led_BlueTooth:
295 return m_leds [1];
296 default:
297 return Led_Off;
298 }
299}
300
301bool iPAQ::setLedState ( OLed l, OLedState st )
302{
303 static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK );
304
305 if ( l == Led_Power ) {
306 if ( fd >= 0 ) {
307 LED_IN leds;
308 ::memset ( &leds, 0, sizeof( leds ));
309 leds. TotalTime = 0;
310 leds. OnTime = 0;
311 leds. OffTime = 1;
312 leds. OffOnBlink = 2;
313
314 switch ( st ) {
315 case Led_Off : leds. OffOnBlink = 0; break;
316 case Led_On : leds. OffOnBlink = 1; break;
317 case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
318 case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
319 }
320
321 if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) {
322 m_leds [0] = st;
323 return true;
324 }
325 }
326 }
327 return false;
328}
329
330
331bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
332{
333 int newkeycode = keycode;
334
335 switch ( keycode ) {
336 // H38xx/H39xx have no "Q" key anymore - this is now the Mail key
337 case HardKey_Menu: {
338 if (( d->m_model == Model_iPAQ_H38xx ) ||
339 ( d->m_model == Model_iPAQ_H39xx ) ||
340 ( d->m_model == Model_iPAQ_H5xxx)) {
341 newkeycode = HardKey_Mail;
342 }
343 break;
344 }
345
346 // Rotate cursor keys 180°
347 case Key_Left :
348 case Key_Right:
349 case Key_Up :
350 case Key_Down : {
351 if (( d->m_model == Model_iPAQ_H31xx ) ||
352 ( d->m_model == Model_iPAQ_H38xx )) {
353 newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4;
354 }
355 break;
356 }
357
358 // map Power Button short/long press to F34/F35
359 case Key_SysReq: {
360 if ( isPress ) {
361 if ( m_power_timer )
362 killTimer ( m_power_timer );
363 m_power_timer = startTimer ( 500 );
364 }
365 else if ( m_power_timer ) {
366 killTimer ( m_power_timer );
367 m_power_timer = 0;
368 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false );
369 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false );
370 }
371 newkeycode = Key_unknown;
372 break;
373 }
374 }
375
376 if ( newkeycode != keycode ) {
377 if ( newkeycode != Key_unknown )
378 QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
379 return true;
380 }
381 else
382 return false;
383}
384
385void iPAQ::timerEvent ( QTimerEvent * )
386{
387 killTimer ( m_power_timer );
388 m_power_timer = 0;
389 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
390 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
391}
392
393
394void iPAQ::alarmSound()
395{
396#ifndef QT_NO_SOUND
397 static Sound snd ( "alarm" );
398 int fd;
399 int vol;
400 bool vol_reset = false;
401
402 if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
403 if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
404 Config cfg ( "qpe" );
405 cfg. setGroup ( "Volume" );
406
407 int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
408 if ( volalarm < 0 )
409 volalarm = 0;
410 else if ( volalarm > 100 )
411 volalarm = 100;
412 volalarm |= ( volalarm << 8 );
413
414 if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
415 vol_reset = true;
416 }
417 }
418
419 snd. play();
420 while ( !snd. isFinished())
421 qApp->processEvents();
422
423 if ( fd >= 0 ) {
424 if ( vol_reset )
425 ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
426 ::close ( fd );
427 }
428#endif
429}
430
431
432bool iPAQ::setSoftSuspend ( bool soft )
433{
434 bool res = false;
435 int fd;
436
437 if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
438 if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
439 res = true;
440 else
441 ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
442
443 ::close ( fd );
444 }
445 else
446 ::perror ( "/proc/sys/ts/suspend_button_mode" );
447
448 return res;
449}
450
451
452bool iPAQ::setDisplayBrightness ( int bright )
453{
454 bool res = false;
455 int fd;
456
457 if ( bright > 255 )
458 bright = 255;
459 if ( bright < 0 )
460 bright = 0;
461
462 if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
463 FLITE_IN bl;
464 bl. mode = 1;
465 bl. pwr = bright ? 1 : 0;
466 bl. brightness = ( bright * ( displayBrightnessResolution() - 1 ) + 127 ) / 255;
467 res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
468 ::close ( fd );
469 }
470 return res;
471}
472
473int iPAQ::displayBrightnessResolution() const
474{
475 switch ( model()) {
476 case Model_iPAQ_H31xx:
477 case Model_iPAQ_H36xx:
478 case Model_iPAQ_H37xx:
479 return 128; // really 256, but >128 could damage the LCD
480
481 case Model_iPAQ_H38xx:
482 case Model_iPAQ_H39xx:
483 return 64;
484 case Model_iPAQ_H5xxx:
485 return 255;
486
487 default:
488 return 2;
489 }
490}
491
492
493bool iPAQ::hasLightSensor() const
494{
495 return true;
496}
497
498int iPAQ::readLightSensor()
499{
500 int fd;
501 int val = -1;
502
503 if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) {
504 char buffer [8];
505
506 if ( ::read ( fd, buffer, 5 ) == 5 ) {
507 char *endptr;
508
509 buffer [4] = 0;
510 val = ::strtol ( buffer + 2, &endptr, 16 );
511
512 if ( *endptr != 0 )
513 val = -1;
514 }
515 ::close ( fd );
516 }
517
518 return val;
519}
520
521int iPAQ::lightSensorResolution() const
522{
523 return 256;
524}