Diffstat (limited to 'libopie2/opiecore/device/odevice_simpad.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opiecore/device/odevice_simpad.cpp | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/libopie2/opiecore/device/odevice_simpad.cpp b/libopie2/opiecore/device/odevice_simpad.cpp new file mode 100644 index 0000000..82dce10 --- a/dev/null +++ b/libopie2/opiecore/device/odevice_simpad.cpp | |||
@@ -0,0 +1,443 @@ | |||
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 | |||
69 | using namespace Opie; | ||
70 | |||
71 | class SIMpad : public ODevice, public QWSServer::KeyboardFilter | ||
72 | { | ||
73 | protected: | ||
74 | virtual void init(); | ||
75 | virtual void initButtons(); | ||
76 | |||
77 | public: | ||
78 | virtual bool setSoftSuspend( bool soft ); | ||
79 | virtual bool suspend(); | ||
80 | |||
81 | virtual bool setDisplayStatus( bool on ); | ||
82 | virtual bool setDisplayBrightness( int b ); | ||
83 | virtual int displayBrightnessResolution() const; | ||
84 | |||
85 | virtual void alarmSound(); | ||
86 | |||
87 | virtual QValueList <OLed> ledList() const; | ||
88 | virtual QValueList <OLedState> ledStateList( OLed led ) const; | ||
89 | virtual OLedState ledState( OLed led ) const; | ||
90 | virtual bool setLedState( OLed led, OLedState st ); | ||
91 | |||
92 | protected: | ||
93 | virtual bool filter( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat ); | ||
94 | virtual void timerEvent( QTimerEvent *te ); | ||
95 | |||
96 | int m_power_timer; | ||
97 | |||
98 | OLedState m_leds [1]; | ||
99 | }; | ||
100 | |||
101 | struct s_button { | ||
102 | uint model; | ||
103 | Qt::Key code; | ||
104 | char *utext; | ||
105 | char *pix; | ||
106 | char *fpressedservice; | ||
107 | char *fpressedaction; | ||
108 | char *fheldservice; | ||
109 | char *fheldaction; | ||
110 | } simpad_buttons [] = { | ||
111 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
112 | Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Lower+Up"), | ||
113 | "devicebuttons/simpad_lower_up", | ||
114 | "datebook", "nextView()", | ||
115 | "today", "raise()" }, | ||
116 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
117 | Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Lower+Down"), | ||
118 | "devicebuttons/simpad_lower_down", | ||
119 | "addressbook", "raise()", | ||
120 | "addressbook", "beamBusinessCard()" }, | ||
121 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
122 | Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Lower+Right"), | ||
123 | "devicebuttons/simpad_lower_right", | ||
124 | "QPE/TaskBar", "toggleMenu()", | ||
125 | "QPE/TaskBar", "toggleStartMenu()" }, | ||
126 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
127 | Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Lower+Left"), | ||
128 | "devicebuttons/simpad_lower_left", | ||
129 | "mail", "raise()", | ||
130 | "mail", "newMail()" }, | ||
131 | |||
132 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
133 | Qt::Key_F5, QT_TRANSLATE_NOOP("Button", "Upper+Up"), | ||
134 | "devicebuttons/simpad_upper_up", | ||
135 | "QPE/Launcher", "home()", | ||
136 | "buttonsettings", "raise()" }, | ||
137 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
138 | Qt::Key_F6, QT_TRANSLATE_NOOP("Button", "Upper+Down"), | ||
139 | "devicebuttons/simpad_upper_down", | ||
140 | "addressbook", "raise()", | ||
141 | "addressbook", "beamBusinessCard()" }, | ||
142 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
143 | Qt::Key_F7, QT_TRANSLATE_NOOP("Button", "Upper+Right"), | ||
144 | "devicebuttons/simpad_upper_right", | ||
145 | "QPE/TaskBar", "toggleMenu()", | ||
146 | "QPE/TaskBar", "toggleStartMenu()" }, | ||
147 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
148 | Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Upper+Left"), | ||
149 | "devicebuttons/simpad_upper_left", | ||
150 | "QPE/Rotation", "flip()", | ||
151 | "QPE/Rotation", "flip()" }, | ||
152 | /* | ||
153 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
154 | Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"), | ||
155 | "devicebuttons/simpad_lower_upper", | ||
156 | "QPE/Launcher", "home()", | ||
157 | "buttonsettings", "raise()" }, | ||
158 | { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, | ||
159 | Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"), | ||
160 | "devicebuttons/simpad_upper_lower", | ||
161 | "QPE/Launcher", "home()", | ||
162 | "buttonsettings", "raise()" }, | ||
163 | */ | ||
164 | }; | ||
165 | |||
166 | void SIMpad::init() | ||
167 | { | ||
168 | d->m_vendorstr = "SIEMENS"; | ||
169 | d->m_vendor = Vendor_SIEMENS; | ||
170 | |||
171 | QFile f ( "/proc/hal/model" ); | ||
172 | |||
173 | //TODO Implement model checking | ||
174 | //FIXME For now we assume an SL4 | ||
175 | |||
176 | d->m_modelstr = "SL4"; | ||
177 | d->m_model = Model_SIMpad_SL4; | ||
178 | |||
179 | switch ( d->m_model ) { | ||
180 | default: | ||
181 | d->m_rotation = Rot0; | ||
182 | d->m_direction = CCW; | ||
183 | d->m_holdtime = 1000; // 1000ms | ||
184 | |||
185 | break; | ||
186 | } | ||
187 | |||
188 | f. setName ( "/etc/familiar-version" ); | ||
189 | if ( f. open ( IO_ReadOnly )) { | ||
190 | d->m_systemstr = "Familiar"; | ||
191 | d->m_system = System_Familiar; | ||
192 | |||
193 | QTextStream ts ( &f ); | ||
194 | d->m_sysverstr = ts. readLine(). mid ( 10 ); | ||
195 | |||
196 | f. close(); | ||
197 | } else { | ||
198 | f. setName ( "/etc/oz_version" ); | ||
199 | |||
200 | if ( f. open ( IO_ReadOnly )) { | ||
201 | d->m_systemstr = "OpenEmbedded/SIMpad"; | ||
202 | d->m_system = System_OpenZaurus; | ||
203 | |||
204 | QTextStream ts ( &f ); | ||
205 | ts.setDevice ( &f ); | ||
206 | d->m_sysverstr = ts. readLine(); | ||
207 | f. close(); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | m_leds [0] = m_leds [1] = Led_Off; | ||
212 | |||
213 | m_power_timer = 0; | ||
214 | |||
215 | } | ||
216 | |||
217 | void SIMpad::initButtons() | ||
218 | { | ||
219 | if ( d->m_buttons ) | ||
220 | return; | ||
221 | |||
222 | if ( isQWS( ) ) | ||
223 | QWSServer::setKeyboardFilter ( this ); | ||
224 | |||
225 | d->m_buttons = new QValueList <ODeviceButton>; | ||
226 | |||
227 | for ( uint i = 0; i < ( sizeof( simpad_buttons ) / sizeof( s_button )); i++ ) { | ||
228 | s_button *sb = simpad_buttons + i; | ||
229 | ODeviceButton b; | ||
230 | |||
231 | if (( sb->model & d->m_model ) == d->m_model ) { | ||
232 | b. setKeycode ( sb->code ); | ||
233 | b. setUserText ( QObject::tr ( "Button", sb->utext )); | ||
234 | b. setPixmap ( Resource::loadPixmap ( sb->pix )); | ||
235 | b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( sb->fpressedservice ), sb->fpressedaction )); | ||
236 | b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( sb->fheldservice ), sb->fheldaction )); | ||
237 | |||
238 | d->m_buttons->append ( b ); | ||
239 | } | ||
240 | } | ||
241 | reloadButtonMapping(); | ||
242 | |||
243 | QCopChannel *sysch = new QCopChannel ( "QPE/System", this ); | ||
244 | connect ( sysch, SIGNAL( received( const QCString &, const QByteArray & )), this, SLOT( systemMessage ( const QCString &, const QByteArray & ))); | ||
245 | } | ||
246 | |||
247 | // SIMpad boardcontrol register CS3 | ||
248 | #define SIMPAD_BOARDCONTROL "/proc/cs3" | ||
249 | #define SIMPAD_VCC_5V_EN 0x0001 // For 5V PCMCIA | ||
250 | #define SIMPAD_VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA | ||
251 | #define SIMPAD_EN1 0x0004 // This is only for EPROM's | ||
252 | #define SIMPAD_EN0 0x0008 // Both should be enable for 3.3V or 5V | ||
253 | #define SIMPAD_DISPLAY_ON 0x0010 | ||
254 | #define SIMPAD_PCMCIA_BUFF_DIS 0x0020 | ||
255 | #define SIMPAD_MQ_RESET 0x0040 | ||
256 | #define SIMPAD_PCMCIA_RESET 0x0080 | ||
257 | #define SIMPAD_DECT_POWER_ON 0x0100 | ||
258 | #define SIMPAD_IRDA_SD 0x0200 // Shutdown for powersave | ||
259 | #define SIMPAD_RS232_ON 0x0400 | ||
260 | #define SIMPAD_SD_MEDIAQ 0x0800 // Shutdown for powersave | ||
261 | #define SIMPAD_LED2_ON 0x1000 | ||
262 | #define SIMPAD_IRDA_MODE 0x2000 // Fast/Slow IrDA mode | ||
263 | #define SIMPAD_ENABLE_5V 0x4000 // Enable 5V circuit | ||
264 | #define SIMPAD_RESET_SIMCARD 0x8000 | ||
265 | |||
266 | //SIMpad touchscreen backlight strength control | ||
267 | #define SIMPAD_BACKLIGHT_CONTROL "/proc/driver/mq200/registers/PWM_CONTROL" | ||
268 | #define SIMPAD_BACKLIGHT_MASK 0x00a10044 | ||
269 | |||
270 | QValueList <OLed> SIMpad::ledList() const | ||
271 | { | ||
272 | QValueList <OLed> vl; | ||
273 | vl << Led_Power; //FIXME which LED is LED2 ? The green one or the amber one? | ||
274 | //vl << Led_Mail; //TODO find out if LED1 is accessible anyway | ||
275 | return vl; | ||
276 | } | ||
277 | |||
278 | QValueList <OLedState> SIMpad::ledStateList ( OLed l ) const | ||
279 | { | ||
280 | QValueList <OLedState> vl; | ||
281 | |||
282 | if ( l == Led_Power ) //FIXME which LED is LED2 ? The green one or the amber one? | ||
283 | vl << Led_Off << Led_On; | ||
284 | //else if ( l == Led_Mail ) //TODO find out if LED1 is accessible anyway | ||
285 | //vl << Led_Off; | ||
286 | return vl; | ||
287 | } | ||
288 | |||
289 | OLedState SIMpad::ledState ( OLed l ) const | ||
290 | { | ||
291 | switch ( l ) { | ||
292 | case Led_Power: | ||
293 | return m_leds [0]; | ||
294 | //case Led_Mail: | ||
295 | //return m_leds [1]; | ||
296 | default: | ||
297 | return Led_Off; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | bool SIMpad::setLedState ( OLed l, OLedState st ) | ||
302 | { | ||
303 | #if 0 | ||
304 | static int fd = ::open ( SIMPAD_BOARDCONTROL, O_RDWR | O_NONBLOCK ); | ||
305 | |||
306 | /*TODO Implement this like that: | ||
307 | read from cs3 | ||
308 | && with SIMPAD_LED2_ON | ||
309 | write to cs3 */ | ||
310 | m_leds [0] = st; | ||
311 | return true; | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | #endif | ||
317 | return false; | ||
318 | } | ||
319 | |||
320 | |||
321 | bool SIMpad::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat ) | ||
322 | { | ||
323 | //TODO | ||
324 | return false; | ||
325 | } | ||
326 | |||
327 | void SIMpad::timerEvent ( QTimerEvent * ) | ||
328 | { | ||
329 | killTimer ( m_power_timer ); | ||
330 | m_power_timer = 0; | ||
331 | QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false ); | ||
332 | QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false ); | ||
333 | } | ||
334 | |||
335 | |||
336 | void SIMpad::alarmSound() | ||
337 | { | ||
338 | #ifndef QT_NO_SOUND | ||
339 | static Sound snd ( "alarm" ); | ||
340 | int fd; | ||
341 | int vol; | ||
342 | bool vol_reset = false; | ||
343 | |||
344 | if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) { | ||
345 | if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) { | ||
346 | Config cfg ( "qpe" ); | ||
347 | cfg. setGroup ( "Volume" ); | ||
348 | |||
349 | int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 ); | ||
350 | if ( volalarm < 0 ) | ||
351 | volalarm = 0; | ||
352 | else if ( volalarm > 100 ) | ||
353 | volalarm = 100; | ||
354 | volalarm |= ( volalarm << 8 ); | ||
355 | |||
356 | if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 ) | ||
357 | vol_reset = true; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | snd. play(); | ||
362 | while ( !snd. isFinished()) | ||
363 | qApp->processEvents(); | ||
364 | |||
365 | if ( fd >= 0 ) { | ||
366 | if ( vol_reset ) | ||
367 | ::ioctl ( fd, MIXER_WRITE( 0 ), &vol ); | ||
368 | ::close ( fd ); | ||
369 | } | ||
370 | #endif | ||
371 | } | ||
372 | |||
373 | |||
374 | bool SIMpad::suspend() // Must override because SIMpad does NOT have apm | ||
375 | { | ||
376 | qDebug( "ODevice for SIMpad: suspend()" ); | ||
377 | if ( !isQWS( ) ) // only qwsserver is allowed to suspend | ||
378 | return false; | ||
379 | |||
380 | bool res = false; | ||
381 | |||
382 | struct timeval tvs, tvn; | ||
383 | ::gettimeofday ( &tvs, 0 ); | ||
384 | |||
385 | ::sync(); // flush fs caches | ||
386 | res = ( ::system ( "cat /dev/fb/0 >/tmp/.buffer; echo > /proc/sys/pm/suspend; cat /tmp/.buffer >/dev/fb/0" ) == 0 ); //TODO make better :) | ||
387 | |||
388 | return res; | ||
389 | } | ||
390 | |||
391 | |||
392 | bool SIMpad::setSoftSuspend ( bool soft ) | ||
393 | { | ||
394 | qDebug( "ODevice for SIMpad: UNHANDLED setSoftSuspend(%s)", soft? "on" : "off" ); | ||
395 | return false; | ||
396 | } | ||
397 | |||
398 | |||
399 | bool SIMpad::setDisplayStatus ( bool on ) | ||
400 | { | ||
401 | qDebug( "ODevice for SIMpad: setDisplayStatus(%s)", on? "on" : "off" ); | ||
402 | |||
403 | bool res = false; | ||
404 | int fd; | ||
405 | |||
406 | QString cmdline = QString().sprintf( "echo %s > /proc/cs3", on ? "0xd41a" : "0xd40a" ); //TODO make better :) | ||
407 | |||
408 | res = ( ::system( (const char*) cmdline ) == 0 ); | ||
409 | |||
410 | return res; | ||
411 | } | ||
412 | |||
413 | |||
414 | bool SIMpad::setDisplayBrightness ( int bright ) | ||
415 | { | ||
416 | qDebug( "ODevice for SIMpad: setDisplayBrightness( %d )", bright ); | ||
417 | bool res = false; | ||
418 | int fd; | ||
419 | |||
420 | if ( bright > 255 ) | ||
421 | bright = 255; | ||
422 | if ( bright < 1 ) | ||
423 | bright = 0; | ||
424 | |||
425 | if (( fd = ::open ( SIMPAD_BACKLIGHT_CONTROL, O_WRONLY )) >= 0 ) { | ||
426 | int value = 255 - bright; | ||
427 | const int mask = SIMPAD_BACKLIGHT_MASK; | ||
428 | value = value << 8; | ||
429 | value += mask; | ||
430 | char writeCommand[100]; | ||
431 | const int count = sprintf( writeCommand, "0x%x\n", value ); | ||
432 | res = ( ::write ( fd, writeCommand, count ) != -1 ); | ||
433 | ::close ( fd ); | ||
434 | } | ||
435 | return res; | ||
436 | } | ||
437 | |||
438 | |||
439 | int SIMpad::displayBrightnessResolution() const | ||
440 | { | ||
441 | return 255; // All SIMpad models share the same display | ||
442 | } | ||
443 | |||