summaryrefslogtreecommitdiff
path: root/libopie2
authorerik <erik>2007-02-08 01:15:31 (UTC)
committer erik <erik>2007-02-08 01:15:31 (UTC)
commitc36a2e25a8875a31957968482ba8a0831a8b0aba (patch) (unidiff)
tree73c5f9231d3fe7157d814d8a948f27e31eb87c81 /libopie2
parentc4aaefcbe64cecb35f1f1bfa10337e95d8ae439c (diff)
downloadopie-c36a2e25a8875a31957968482ba8a0831a8b0aba.zip
opie-c36a2e25a8875a31957968482ba8a0831a8b0aba.tar.gz
opie-c36a2e25a8875a31957968482ba8a0831a8b0aba.tar.bz2
This commit provides support for any iPAQ handheld that runs a 2.6 kernel
and follows the backlight class in sysfs. This patch was originally done by an unknown poster and maintained by Paul S. Thanks all who contributed.
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/device/odevice_ipaq.cpp101
1 files changed, 44 insertions, 57 deletions
diff --git a/libopie2/opiecore/device/odevice_ipaq.cpp b/libopie2/opiecore/device/odevice_ipaq.cpp
index 16ecc27..02b685a 100644
--- a/libopie2/opiecore/device/odevice_ipaq.cpp
+++ b/libopie2/opiecore/device/odevice_ipaq.cpp
@@ -208,335 +208,322 @@ void iPAQ::init(const QString& model)
208 208
209 m_power_timer = 0; 209 m_power_timer = 0;
210 210
211} 211}
212 212
213void iPAQ::initButtons() 213void iPAQ::initButtons()
214{ 214{
215 if ( d->m_buttons ) 215 if ( d->m_buttons )
216 return; 216 return;
217 217
218 if ( isQWS( ) ) { 218 if ( isQWS( ) ) {
219 addPreHandler(this); 219 addPreHandler(this);
220 } 220 }
221 221
222 d->m_buttons = new QValueList <ODeviceButton>; 222 d->m_buttons = new QValueList <ODeviceButton>;
223 223
224 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) { 224 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
225 i_button *ib = ipaq_buttons + i; 225 i_button *ib = ipaq_buttons + i;
226 ODeviceButton b; 226 ODeviceButton b;
227 227
228 if (( ib->model & d->m_model ) == d->m_model ) { 228 if (( ib->model & d->m_model ) == d->m_model ) {
229 b. setKeycode ( ib->code ); 229 b. setKeycode ( ib->code );
230 b. setUserText ( QObject::tr ( "Button", ib->utext )); 230 b. setUserText ( QObject::tr ( "Button", ib->utext ));
231 b. setPixmap ( OResource::loadPixmap ( ib->pix )); 231 b. setPixmap ( OResource::loadPixmap ( ib->pix ));
232 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib->fpressedservice ), ib->fpressedaction )); 232 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib->fpressedservice ), ib->fpressedaction ));
233 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib->fheldservice ), ib->fheldaction )); 233 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib->fheldservice ), ib->fheldaction ));
234 234
235 d->m_buttons->append ( b ); 235 d->m_buttons->append ( b );
236 } 236 }
237 } 237 }
238 reloadButtonMapping(); 238 reloadButtonMapping();
239} 239}
240 240
241QValueList <OLed> iPAQ::ledList() const 241QValueList <OLed> iPAQ::ledList() const
242{ 242{
243 QValueList <OLed> vl; 243 QValueList <OLed> vl;
244 vl << Led_Power; 244 vl << Led_Power;
245 245
246 if ( d->m_model == Model_iPAQ_H38xx ) 246 if ( d->m_model == Model_iPAQ_H38xx )
247 vl << Led_BlueTooth; 247 vl << Led_BlueTooth;
248 return vl; 248 return vl;
249} 249}
250 250
251QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const 251QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const
252{ 252{
253 QValueList <OLedState> vl; 253 QValueList <OLedState> vl;
254 254
255 if ( l == Led_Power ) 255 if ( l == Led_Power )
256 vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast; 256 vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast;
257 else if ( l == Led_BlueTooth && d->m_model == Model_iPAQ_H38xx ) 257 else if ( l == Led_BlueTooth && d->m_model == Model_iPAQ_H38xx )
258 vl << Led_Off; // << Led_On << ??? 258 vl << Led_Off; // << Led_On << ???
259 259
260 return vl; 260 return vl;
261} 261}
262 262
263OLedState iPAQ::ledState ( OLed l ) const 263OLedState iPAQ::ledState ( OLed l ) const
264{ 264{
265 switch ( l ) { 265 switch ( l ) {
266 case Led_Power: 266 case Led_Power:
267 return m_leds [0]; 267 return m_leds [0];
268 case Led_BlueTooth: 268 case Led_BlueTooth:
269 return m_leds [1]; 269 return m_leds [1];
270 default: 270 default:
271 return Led_Off; 271 return Led_Off;
272 } 272 }
273} 273}
274 274
275bool iPAQ::setLedState ( OLed l, OLedState st ) 275bool iPAQ::setLedState ( OLed l, OLedState st )
276{ 276{
277 static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK ); 277 static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK );
278 278
279 if ( l == Led_Power ) { 279 if ( l == Led_Power ) {
280 if ( fd >= 0 ) { 280 if ( fd >= 0 ) {
281 LED_IN leds; 281 LED_IN leds;
282 ::memset ( &leds, 0, sizeof( leds )); 282 ::memset ( &leds, 0, sizeof( leds ));
283 leds. TotalTime = 0; 283 leds. TotalTime = 0;
284 leds. OnTime = 0; 284 leds. OnTime = 0;
285 leds. OffTime = 1; 285 leds. OffTime = 1;
286 leds. OffOnBlink = 2; 286 leds. OffOnBlink = 2;
287 287
288 switch ( st ) { 288 switch ( st ) {
289 case Led_Off : leds. OffOnBlink = 0; break; 289 case Led_Off : leds. OffOnBlink = 0; break;
290 case Led_On : leds. OffOnBlink = 1; break; 290 case Led_On : leds. OffOnBlink = 1; break;
291 case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break; 291 case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
292 case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break; 292 case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
293 } 293 }
294 294
295 if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) { 295 if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) {
296 m_leds [0] = st; 296 m_leds [0] = st;
297 return true; 297 return true;
298 } 298 }
299 } 299 }
300 } 300 }
301 return false; 301 return false;
302} 302}
303 303
304 304
305bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat ) 305bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
306{ 306{
307 int newkeycode = keycode; 307 int newkeycode = keycode;
308 308
309 switch ( keycode ) { 309 switch ( keycode ) {
310 // H38xx/H39xx have no "Q" key anymore - this is now the Mail key 310 // H38xx/H39xx have no "Q" key anymore - this is now the Mail key
311 case HardKey_Menu: { 311 case HardKey_Menu: {
312 if (( d->m_model == Model_iPAQ_H38xx ) || 312 if (( d->m_model == Model_iPAQ_H38xx ) ||
313 ( d->m_model == Model_iPAQ_H39xx ) || 313 ( d->m_model == Model_iPAQ_H39xx ) ||
314 ( d->m_model == Model_iPAQ_H5xxx)) { 314 ( d->m_model == Model_iPAQ_H5xxx)) {
315 newkeycode = HardKey_Mail; 315 newkeycode = HardKey_Mail;
316 } 316 }
317 break; 317 break;
318 } 318 }
319 319
320 // Rotate cursor keys 180 or 270 320 // Rotate cursor keys 180 or 270
321 case Key_Left : 321 case Key_Left :
322 case Key_Right: 322 case Key_Right:
323 case Key_Up : 323 case Key_Up :
324 case Key_Down : { 324 case Key_Down : {
325 if (( d->m_model == Model_iPAQ_H31xx ) || 325 if (( d->m_model == Model_iPAQ_H31xx ) ||
326 ( d->m_model == Model_iPAQ_H38xx )) { 326 ( d->m_model == Model_iPAQ_H38xx )) {
327 newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4; 327 newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4;
328 } 328 }
329 // Rotate the cursor keys by 270 329 // Rotate the cursor keys by 270
330 // keycode - Key_Left = position of the button starting from left clockwise 330 // keycode - Key_Left = position of the button starting from left clockwise
331 // add the rotation to it and modolo. No we've the original offset 331 // add the rotation to it and modolo. No we've the original offset
332 // add the offset to the Key_Left key 332 // add the offset to the Key_Left key
333 if (( d->m_model == Model_iPAQ_H5xxx ) || 333 if (( d->m_model == Model_iPAQ_H5xxx ) ||
334 ( d->m_model == Model_iPAQ_H191x ) || 334 ( d->m_model == Model_iPAQ_H191x ) ||
335 ( d->m_model == Model_iPAQ_H4xxx ) || 335 ( d->m_model == Model_iPAQ_H4xxx ) ||
336 ( d->m_model == Model_iPAQ_H1940 )) 336 ( d->m_model == Model_iPAQ_H1940 ))
337 newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4; 337 newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4;
338 break; 338 break;
339 } 339 }
340 340
341 // map Power Button short/long press to F34/F35 341 // map Power Button short/long press to F34/F35
342 case HardKey_Suspend: // Hope we don't have infinite recursion here 342 case HardKey_Suspend: // Hope we don't have infinite recursion here
343 case Key_SysReq: { 343 case Key_SysReq: {
344 if ( isPress ) { 344 if ( isPress ) {
345 if ( m_power_timer ) 345 if ( m_power_timer )
346 killTimer ( m_power_timer ); 346 killTimer ( m_power_timer );
347 m_power_timer = startTimer ( 500 ); 347 m_power_timer = startTimer ( 500 );
348 } 348 }
349 else if ( m_power_timer ) { 349 else if ( m_power_timer ) {
350 killTimer ( m_power_timer ); 350 killTimer ( m_power_timer );
351 m_power_timer = 0; 351 m_power_timer = 0;
352 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false ); 352 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false );
353 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false ); 353 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false );
354 } 354 }
355 newkeycode = Key_unknown; 355 newkeycode = Key_unknown;
356 break; 356 break;
357 } 357 }
358 } 358 }
359 359
360 if ( newkeycode != keycode ) { 360 if ( newkeycode != keycode ) {
361 if ( newkeycode != Key_unknown ) 361 if ( newkeycode != Key_unknown )
362 QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat ); 362 QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
363 return true; 363 return true;
364 } 364 }
365 else 365 else
366 return false; 366 return false;
367} 367}
368 368
369void iPAQ::timerEvent ( QTimerEvent * ) 369void iPAQ::timerEvent ( QTimerEvent * )
370{ 370{
371 killTimer ( m_power_timer ); 371 killTimer ( m_power_timer );
372 m_power_timer = 0; 372 m_power_timer = 0;
373 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false ); 373 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
374 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false ); 374 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
375} 375}
376 376
377 377
378void iPAQ::playAlarmSound() 378void iPAQ::playAlarmSound()
379{ 379{
380#ifndef QT_NO_SOUND 380#ifndef QT_NO_SOUND
381 static Sound snd ( "alarm" ); 381 static Sound snd ( "alarm" );
382 if(!snd.isFinished()) 382 if(!snd.isFinished())
383 return; 383 return;
384 384
385 changeMixerForAlarm(0, "/dev/sound/mixer", &snd ); 385 changeMixerForAlarm(0, "/dev/sound/mixer", &snd );
386 snd. play(); 386 snd. play();
387#endif 387#endif
388} 388}
389 389
390bool iPAQ::setDisplayBrightness ( int bright ) 390bool iPAQ::setDisplayBrightness ( int bright )
391{ 391{
392 bool res = false; 392 bool res = false;
393 int fd; 393 int fd;
394 394
395 if ( bright > 255 ) 395 if ( bright > 255 )
396 bright = 255; 396 bright = 255;
397 if ( bright < 0 ) 397 if ( bright < 0 )
398 bright = 0; 398 bright = 0;
399 399
400 QString cmdline; 400 QDir sysClass( "/sys/class/backlight/" );
401 401 sysClass.setFilter(QDir::Dirs);
402 switch ( model()) { 402 if ( sysClass.exists() && sysClass.count() > 2 ) {
403 case Model_iPAQ_H191x: 403 QString sysClassPath = sysClass.absFilePath( sysClass[2] + "/brightness" );
404 case Model_iPAQ_H4xxx: 404 int fd = ::open( sysClassPath, O_WRONLY|O_NONBLOCK );
405 { 405 if ( fd ) {
406 QDir sysClass( "/sys/class/backlight/pxafb/" ); 406 char buf[100];
407 sysClass.setFilter(QDir::Dirs); 407 int val = bright * displayBrightnessResolution() / 255;
408 int fd; 408 int len = ::snprintf( &buf[0], sizeof buf, "%d", val );
409 if ( sysClass.exists() ) { 409 res = ( ::write( fd, &buf[0], len ) == 0 );
410 QString sysClassPath = sysClass.absFilePath( "/sys/class/backlight/pxafb/power" ); 410 ::close( fd );
411 fd = ::open( sysClassPath, O_WRONLY | O_NONBLOCK ); 411 }
412 if ( fd ) { 412 } else {
413 char buf[10];
414 buf[0] = bright ? 0 : 4;
415 buf[1] = '\0';
416 res = ( ::write( fd, &buf[0], 2 ) == 0 );
417 ::close( fd );
418 }
419 sysClassPath = sysClass.absFilePath( "/sys/class/backlight/pxafb/brightness" );
420 fd = ::open( sysClassPath, O_WRONLY | O_NONBLOCK );
421 if ( fd ) {
422 char buf[100];
423 int len = ::snprintf( &buf[0], sizeof buf, "%d", bright );
424 res = ( ::write( fd, &buf[0], len ) == 0 );
425 ::close( fd );
426 }
427 }
428 }
429 break;
430
431 case Model_iPAQ_HX4700:
432 cmdline = QString::fromLatin1( "echo %1 > /sys/class/backlight/w100fb/brightness" ).arg( bright );
433 // No Global::shellQuote as we gurantee it to be sane
434 res = ( ::system( QFile::encodeName(cmdline) ) == 0 );
435 break;
436
437
438 default:
439 if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) { 413 if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
440 FLITE_IN bl; 414 FLITE_IN bl;
441 bl. mode = 1; 415 bl. mode = 1;
442 bl. pwr = bright ? 1 : 0; 416 bl. pwr = bright ? 1 : 0;
443 bl. brightness = ( bright * ( displayBrightnessResolution() - 1 ) + 127 ) / 255; 417 bl. brightness = ( bright * ( displayBrightnessResolution() - 1 ) + 127 ) / 255;
444 res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 ); 418 res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
445 ::close ( fd ); 419 ::close ( fd );
446 } 420 }
447 } 421 }
422
448 return res; 423 return res;
449} 424}
450 425
451int iPAQ::displayBrightnessResolution() const 426int iPAQ::displayBrightnessResolution() const
452{ 427{
428 int res = 16;
429
430 QDir sysClass( "/sys/class/backlight/" );
431 sysClass.setFilter(QDir::Dirs);
432 if ( sysClass.exists() && sysClass.count() > 2 ) {
433 QString sysClassPath = sysClass.absFilePath( sysClass[2] + "/max_brightness" );
434 int fd = ::open( sysClassPath, O_RDONLY|O_NONBLOCK );
435 if ( fd ) {
436 char buf[100];
437 if ( ::read( fd, &buf[0], sizeof buf ) )
438 ::sscanf( &buf[0], "%d", &res );
439 ::close( fd );
440 }
441 return res;
442 }
443
453 switch ( model()) { 444 switch ( model()) {
454 case Model_iPAQ_H31xx: 445 case Model_iPAQ_H31xx:
455 case Model_iPAQ_H36xx: 446 case Model_iPAQ_H36xx:
456 case Model_iPAQ_H37xx: 447 case Model_iPAQ_H37xx:
457 return 128; // really 256, but >128 could damage the LCD 448 return 128; // really 256, but >128 could damage the LCD
458 449
459 case Model_iPAQ_H38xx: 450 case Model_iPAQ_H38xx:
460 case Model_iPAQ_H39xx: 451 case Model_iPAQ_H39xx:
461 return 64; 452 return 64;
462 case Model_iPAQ_H5xxx: 453 case Model_iPAQ_H5xxx:
463 case Model_iPAQ_HX4700: 454 case Model_iPAQ_HX4700:
464 case Model_iPAQ_H4xxx: 455 case Model_iPAQ_H4xxx:
465 return 255; 456 return 255;
466 case Model_iPAQ_H191x: 457 case Model_iPAQ_H191x:
467 return 7; 458 return 7;
468 case Model_iPAQ_H1940: 459 case Model_iPAQ_H1940:
469 return 44; 460 return 44;
470 default: 461 default:
471 return 2; 462 return 2;
472 } 463 }
473} 464}
474 465
475bool iPAQ::setDisplayStatus ( bool on ) 466bool iPAQ::setDisplayStatus ( bool on )
476{ 467{
477 bool res = false; 468 bool res = false;
478 469
479 QString cmdline; 470 QString cmdline;
480 471
481 if ( model() == Model_iPAQ_H191x ) { 472 QDir sysClass( "/sys/class/lcd/" );
482 QDir sysClass( "/sys/class/lcd/pxafb/" ); 473 sysClass.setFilter(QDir::Dirs);
483 sysClass.setFilter(QDir::Dirs); 474 if ( sysClass.exists() && sysClass.count() > 2 ) {
484 if ( sysClass.exists() ) { 475 QString sysClassPath = sysClass.absFilePath( sysClass[2] + "/power" );
485 QString sysClassPath = sysClass.absFilePath( "/sys/class/lcd/pxafb/power" ); 476 int fd = ::open( sysClassPath, O_WRONLY|O_NONBLOCK );
486 int fd = ::open( sysClassPath, O_WRONLY | O_NONBLOCK ); 477 if ( fd ) {
487 if ( fd ) { 478 char buf[10];
488 char buf[10]; 479 buf[0] = on ? 0 : 4;
489 buf[0] = on ? 0 : 4; 480 buf[1] = '\0';
490 buf[1] = '\0'; 481 res = ( ::write( fd, &buf[0], 2 ) == 0 );
491 res = ( ::write( fd, &buf[0], 2 ) == 0 ); 482 ::close( fd );
492 ::close( fd ); 483 }
493 }
494 }
495 return res;
496 } else { 484 } else {
497 return OAbstractMobileDevice::setDisplayStatus(on); 485 res = OAbstractMobileDevice::setDisplayStatus(on);
498 } 486 }
499 487
500 res = ( ::system( QFile::encodeName(cmdline) ) == 0 );
501
502 return res; 488 return res;
503} 489}
504 490
505bool iPAQ::hasLightSensor() const 491bool iPAQ::hasLightSensor() const
506{ 492{
507 switch (model()) { 493 switch (model()) {
508 case Model_iPAQ_H191x: 494 case Model_iPAQ_H191x:
495 case Model_iPAQ_H22xx:
509 case Model_iPAQ_H4xxx: 496 case Model_iPAQ_H4xxx:
510 return false; 497 return false;
511 default: 498 default:
512 return true; 499 return true;
513 } 500 }
514} 501}
515 502
516int iPAQ::readLightSensor() 503int iPAQ::readLightSensor()
517{ 504{
518 int fd; 505 int fd;
519 int val = -1; 506 int val = -1;
520 507
521 if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) { 508 if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) {
522 char buffer [8]; 509 char buffer [8];
523 510
524 if ( ::read ( fd, buffer, 5 ) == 5 ) { 511 if ( ::read ( fd, buffer, 5 ) == 5 ) {
525 char *endptr; 512 char *endptr;
526 513
527 buffer [4] = 0; 514 buffer [4] = 0;
528 val = ::strtol ( buffer + 2, &endptr, 16 ); 515 val = ::strtol ( buffer + 2, &endptr, 16 );
529 516
530 if ( *endptr != 0 ) 517 if ( *endptr != 0 )
531 val = -1; 518 val = -1;
532 } 519 }
533 ::close ( fd ); 520 ::close ( fd );
534 } 521 }
535 522
536 return val; 523 return val;
537} 524}
538 525
539int iPAQ::lightSensorResolution() const 526int iPAQ::lightSensorResolution() const
540{ 527{
541 return 256; 528 return 256;
542} 529}