Logo Search packages:      
Sourcecode: pbbuttonsd version File versions  Download package

module_display.c

/* --------------------------------------------------------------------------
 * module_display.c
 * code for module display
 *
 * Copyright 2002 Matthias Grimm
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 * -------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "pbbinput.h"
#include <pbb.h>

#include "input_manager.h"
#include "config_manager.h"
#include "module_display.h"
#include "support.h"
#include "gettext_macros.h"

#include <linux/radeonfb.h>

struct moddata_display {
      char *fbdev;         /* pathname of the framebuffer device */
      struct display_flags flags;
      struct display_light lcdlight; /* structures for LCD light control */
      struct display_light kbdlight; /* structures for keyboard light control */

      int autoadj_min_bat;   /* autoadjustment range parameters */
      int autoadj_max_bat;
      int autoadj_min_ac;
      int autoadj_max_ac;

      int kbdon_brightness;   /* keyboard brightness after switch on */
      
      unsigned short keylcdup;  /* keycodes and modifiers */
      unsigned short modlcdup;   /*     for LCD backlight controls */
      unsigned short keylcddn;
      unsigned short modlcddn;
      unsigned short keykbdup;    /* keycodes and modifiers */
      unsigned short modkbdup;    /*     for keyboard illumination controls */
      unsigned short keykbddn;
      unsigned short modkbddn;
      unsigned short keykbdon;
      unsigned short modkbdon;
      unsigned short keymirror;  /* keycode for CRT mirror key */
      unsigned short modmirror;
} modbase_display;

int
display_init ()
{
      struct moddata_display *base = &modbase_display;
      static char devbuffer_fb[STDBUFFERLEN];
      int sid;

      bzero (base, sizeof (struct moddata_display));
      sprintf(devbuffer_fb, DEFAULT_FB_DEVICE);
      base->fbdev  = devbuffer_fb;

      if ((sid = registerCfgSection ("MODULE DISPLAY")) == 0) {
            print_msg (PBB_ERR, _("Can't register configuration section %s, out of memory."), "MODULE DISPLAY");
            return E_NOMEM;
      } else {
            registerCfgOptionInt (sid, "LCD_Brightness", TAG_LCDBRIGHTNESS, 0,
                        N_("initial LCD brightness level"));
            registerCfgOptionInt (sid, "LCD_FadingSpeed", TAG_LCDFADINGSPEED, 0,
                        N_("0 = no smooth fading"));
            registerCfgOptionBool (sid, "LCD_AutoAdjust", TAG_LCDAUTOADJUST, 0,
                        N_("only on Aluminum PowerBooks"));
            registerCfgOptionKey (sid, "LCD_IllumUpKey", TAG_LCDILLUMUPKEY, TAG_LCDILLUMUPMOD, 0,
                        NULL);
            registerCfgOptionKey (sid, "LCD_IllumDownKey", TAG_LCDILLUMDOWNKEY, TAG_LCDILLUMDOWNMOD, 0,
                        NULL);
            registerCfgOptionInt (sid, "LCD_Threshold", TAG_LCDTHRESHOLD, 0,
                        N_("ambient light threshold in percent for backlight autoadj."));
            registerCfgOptionInt (sid, "LCD_AutoAdjMin_Bat", TAG_LCDAUTOADJMINBAT, 0,
                        N_("autoadjustment range parameters"));
            registerCfgOptionInt (sid, "LCD_AutoAdjMax_Bat", TAG_LCDAUTOADJMAXBAT, 0,
                        NULL);
            registerCfgOptionInt (sid, "LCD_AutoAdjMin_AC", TAG_LCDAUTOADJMINAC, 0,
                        NULL);
            registerCfgOptionInt (sid, "LCD_AutoAdjMax_AC", TAG_LCDAUTOADJMAXAC, 0,
                        NULL);
            registerCfgOptionInt (sid, "KBD_Brightness", TAG_KBDBRIGHTNESS, 0,
                        N_("initial keyboard illumination level"));
            registerCfgOptionInt (sid, "KBD_OnBrightness", TAG_KBDONBRIGHTNESS, 0,
                        N_("initial level if KBD on/off key is pressed"));
            registerCfgOptionInt (sid, "KBD_FadingSpeed", TAG_KBDFADINGSPEED, 0,
                        N_("0 = no smooth fading"));
            registerCfgOptionBool (sid, "KBD_AutoAdjust", TAG_KBDAUTOADJUST, 0,
                        N_("only on Aluminum PowerBooks"));
            registerCfgOptionKey (sid, "KBD_IllumUpKey", TAG_KBDILLUMUPKEY, TAG_KBDILLUMUPMOD, 0,
                        NULL);
            registerCfgOptionKey (sid, "KBD_IllumDownKey", TAG_KBDILLUMDOWNKEY, TAG_KBDILLUMDOWNMOD, 0,
                        NULL);
            registerCfgOptionKey (sid, "KBD_IllumOnKey", TAG_KBDILLUMONKEY, TAG_KBDILLUMONMOD, 0,
                        NULL);
            registerCfgOptionInt (sid, "KBD_Threshold", TAG_KBDTHRESHOLD, 0,
                        N_("ambient light threshold in percent for keyboard light autoadj."));
            registerCfgOptionString (sid, "dev_FrameBuffer", TAG_FRAMEBUFFERDEVICE, 0,
                        NULL);
            registerCfgOptionBool (sid, "UseFBBlank", TAG_BLANKFRAMEBUFFER, 0,
                        NULL);
            registerCfgOptionBool (sid, "DimFullyDark", TAG_DIMFULLYDARK, 0,
                        NULL);
            registerCfgOptionKey (sid, "CRT_MirrorKey", TAG_CRTMIRRORKEY, TAG_CRTMIRRORMOD, 0,
                        NULL);
      }

      register_function (QUERYQUEUE, display_query);
      register_function (CONFIGQUEUE, display_configure);
      return 0;
}

int
display_open (struct tagitem *taglist)
{
      struct moddata_display *base = &modbase_display;
      struct tagitem args[] = {{ TAG_BACKLIGHTMAX, 0 },
                               { TAG_BACKLIGHTLEVEL, -1 },
                               { TAG_KEYBLIGHTMAX, 0 },
                               { TAG_AMBIENTLIGHT, -1 },
                               { TAG_END, 0 }};
      int level;

      process_queue (QUERYQUEUE, args); /* get some information from hardware module */

      /* if no backlight controller was registered TAG_BACKLIGHTLEVEL
       * would return -1 which must be converted to be in brightness
       * range. furtheron a flag saves this information.
       */
      base->flags.nobacklight = 0;
      if ((level = (int) tagfind (args, TAG_BACKLIGHTLEVEL, -1)) == -1) {
            level = (int) tagfind (args, TAG_BACKLIGHTMAX, 0);
            base->flags.nobacklight = 1;
      }
            
      base->lcdlight.current     = level;
      base->lcdlight.target      = level;
      base->lcdlight.max         = (int) tagfind (args, TAG_BACKLIGHTMAX, 0);
      base->lcdlight.backup      = level;
      base->lcdlight.offset      = 0;
      base->lcdlight.fadingspeed = 0;
      base->lcdlight.fadingcount = 0;
      base->lcdlight.threshold   = 94; /* value in percent */

      base->kbdlight.current     = 0;
      base->kbdlight.target      = 0;
      base->kbdlight.max         = (int) tagfind (args, TAG_KEYBLIGHTMAX, 0);
      base->kbdlight.backup      = 0;
      base->kbdlight.offset      = 0;
      base->kbdlight.fadingspeed = 5;
      base->kbdlight.fadingcount = 0;
      base->kbdlight.threshold   = 28;  /* value in percent */
      process_queue_single (CONFIGQUEUE, TAG_KEYBLIGHTLEVEL, base->kbdlight.current);

      base->keylcdup    = KEY_BRIGHTNESSUP;
      base->modlcdup    = MOD_NONE;
      base->keylcddn    = KEY_BRIGHTNESSDOWN;
      base->modlcddn    = MOD_NONE;
      base->keykbdup    = KEY_KBDILLUMUP;     /* key not officially supported yet */
      base->modkbdup    = MOD_NONE;
      base->keykbddn    = KEY_KBDILLUMDOWN;   /* key not officially supported yet */
      base->modkbddn    = MOD_NONE;
      base->keykbdon    = KEY_KBDILLUMTOGGLE; /* key not officially supported yet */
      base->modkbdon    = MOD_NONE;
      base->keymirror = KEY_F7;
      base->modmirror = MOD_CTRL;

      base->autoadj_min_bat = 1;
      base->autoadj_max_bat = base->lcdlight.max / 2 + 1;
      base->autoadj_min_ac  = 1;
      base->autoadj_max_ac  = base->lcdlight.max;
      
      base->kbdon_brightness = KBD_BRIGHTNESS_MIN; /* saved brighhtness for kbd on/off key */
      
      base->flags.status         = STATUS_NORMAL;
      base->flags.lmu_enable     = tagfind(args, TAG_AMBIENTLIGHT, -1) == -1 ? 0 : 1;
      base->flags.ctrl_fb        = 0;  /* framebuffer disabled by default  */
      base->flags.dimfullydark   = 0;  /* don't dim to complete darkness by default */
      base->flags.lcd_autoadjust = 1;  /* lcd and keyboard should react on */
      base->flags.kbd_autoadjust = 1;  /* ambient light if available       */
      base->flags.coveropen      = 1;  /* cover open by default same as in laptop module */

      /* This value must be set to 1 if the initial value of kbd_onbrightness should
       * take effect but this will block KBD autoadjustment mode. In KBD autoadjustement
       * mode the initial value makes no sense so we set the flag dependent of the
       * users autoadjustment settings.
       * In case somebody set the keyboard brightness from extern the kbd_switchedoff
       * flag will always be 0 except the current brightness is zero (dark). This flag
       * status is set by display_handle_tags(), TAG_KBDBRIGHTNESS.
       */
      if (base->kbdlight.current == 0)
            base->flags.kbd_switchedoff= !base->flags.kbd_autoadjust; 

      register_function (KBDQUEUE, display_keyboard);
      register_function (T10QUEUE, display_timer);
      register_function (T1000QUEUE, display_ambienttimer);
      return 0;
}

int
display_close ()
{
      return 0;
}

int
display_exit ()
{
      return 0;
}

/* This functions handles keyboard events
 * The keyboard illumination can be switched on/off with a
 * special key. Because the current brightness value could
 * not be read from hardware, it is saved statically in
 * this function. This is not the best sollution, but this
 * won't conflicting with the backup value needed by the
 * automatic adjustment function.
 * In autoadjust mode the appropriate keys change their
 * meaning. Instead of modifying the brightness directly the
 * keys now modify an offset that will shift the characteristic
 * curve for automatic brightness adjustment up or down a bit.
 * Although automatic adjustment ist enable the user keep
 * control over the brightness.
 * Functions using the shift modifier is disabled during
 * automatic control.
 */
void
display_keyboard (struct tagitem *taglist)
{
      struct moddata_display *base = &modbase_display;
      int code, value, mod, level = 0, changed = 0, tmp;

      code = (int) tagfind (taglist, TAG_KEYCODE, 0);
      value = (int) tagfind (taglist, TAG_KEYREPEAT, 0);
      mod = (int) tagfind (taglist, TAG_MODIFIER, 0);

      if (value && base->flags.coveropen) {
            /* key for video mirroring */
            if ((code == base->keymirror) && (mod == base->modmirror))
                  if ((tmp = display_switchmirror ()) != -1)
                        singletag_to_clients(CHANGEVALUE, TAG_CRTMIRROR, tmp);
            
            /* keys for LCD brightness control */
            if ((code == base->keylcdup) && ((mod & ~MOD_SHIFT) == base->modlcdup)) {
                  /* somebody might have changed the brightness level directly so
                   * check if we are still synchron here
                   */
                  display_sync_lcdbrightness ();
                  
                  /* .target and .current will normally be the same value synchronized
                   * by the display_timer() function. We use .target here because the
                   * powersave module might have given an order to change brightness.
                   * In case fading was activated this order would not be fullfilled
                   * yet (only .target has been set accordingly) and if we used
                   * .current here we would overwrite it.
                   */
                  level = mod & MOD_SHIFT ? base->lcdlight.max : base->lcdlight.target + 1;
                  changed = 1;
            } else if ((code == base->keylcddn) && ((mod & ~MOD_SHIFT) == base->modlcddn)) {
                  display_sync_lcdbrightness ();  /* same as brightness up */
                  level = mod & MOD_SHIFT ? LCD_BRIGHTNESS_MIN : base->lcdlight.target - 1;
                  changed = 1;
            }
            
            /* keys for KBD illumination control */
            if ((code == base->keykbdup) && ((mod & ~MOD_SHIFT) == base->modkbdup)) {
                  if (base->flags.kbd_switchedoff) {
                        base->kbdlight.current = base->kbdon_brightness;
                        base->flags.kbd_switchedoff = 0;
                  }
                  level = mod & MOD_SHIFT ? base->kbdlight.max : base->kbdlight.current + 1;
                  changed = 2;
            } else if ((code == base->keykbddn) && ((mod & ~MOD_SHIFT) == base->modkbddn)) {
                  if (base->flags.kbd_switchedoff) {
                        base->kbdlight.current = base->kbdon_brightness;
                        base->flags.kbd_switchedoff = 0;
                  }
                  level = mod & MOD_SHIFT ? KBD_BRIGHTNESS_MIN : base->kbdlight.current - 1;
                  changed = 2;
            } else if (base->flags.lmu_enable && (code == base->keykbdon) && (mod == base->modkbdon)) {
                  if (base->flags.kbd_switchedoff) {
                        level = base->kbdon_brightness;
                        base->flags.kbd_switchedoff = 0;
                  } else {
                        base->kbdon_brightness = base->kbdlight.current;
                        base->flags.kbd_switchedoff = 1;
                        level = KBD_BRIGHTNESS_OFF;
                  }
                  level = display_set_kbdbrightness(level);
                  singletag_to_clients(CHANGEVALUE, TAG_KBDBRIGHTNESS, level);
            }

            switch (changed) {
            case 1:  /* LCD brightness level changed by keys */
                  if (base->flags.lmu_enable && base->flags.lcd_autoadjust) {
                        if (mod & MOD_SHIFT)
                              break;   /* shift modifier disabled in automatic mode */
                        tmp = base->lcdlight.current - base->lcdlight.offset;
                        base->lcdlight.offset += (level - base->lcdlight.current) > 0 ? 1 : -1;
                        if (tmp + base->lcdlight.offset > base->lcdlight.max)
                              base->lcdlight.offset = base->lcdlight.max - tmp;
                        if (tmp + base->lcdlight.offset < 1)
                              base->lcdlight.offset = -tmp + 1;
                        level = tmp + base->lcdlight.offset;
                  }
                  level = display_set_lcdbrightness(level);
                  singletag_to_clients(CHANGEVALUE, TAG_LCDBRIGHTNESS, level);
                  break;
            case 2:  /* Keyboard illumination level changed by keys */
                  if (base->flags.lmu_enable) {
                        if (base->flags.kbd_autoadjust) {
                              if (mod & MOD_SHIFT)
                                    break;   /* shift modifier disabled in automatic mode */
                              tmp = base->kbdlight.current - base->kbdlight.offset;
                              base->kbdlight.offset += (level - base->kbdlight.current) > 0 ? 1 : -1;
                              if (tmp + base->kbdlight.offset > base->kbdlight.max)
                                    base->kbdlight.offset = base->kbdlight.max - tmp;
                              if (tmp + base->kbdlight.offset < 0)
                                    base->kbdlight.offset = -tmp;
                              level = tmp + base->kbdlight.offset;
                        }
                        level = display_set_kbdbrightness(level);
                        singletag_to_clients(CHANGEVALUE, TAG_KBDBRIGHTNESS, level);
                  }
                  break;
            }
      }
}

/* Timer function called every 10ms.
 * The current brightness level for each lightsource will
 * be modified to match the appropriate target level. This
 * modification could be done hardly or smoothly depending
 * on certain parameters set or not.
 * This function will react automatically as soon as the
 * current brightness level differs from the target level.
 */
void
display_timer (struct tagitem *taglist)
{
      struct moddata_display *base = &modbase_display;

      if (base->lcdlight.current != base->lcdlight.target) {
            base->lcdlight.fadingcount++;
            if (base->lcdlight.fadingcount >= base->lcdlight.fadingspeed) {
                  base->lcdlight.fadingcount = 0;
                  if (base->lcdlight.fadingspeed) {
                        if (base->lcdlight.current > base->lcdlight.target)
                              base->lcdlight.current--;   /* target is darker as current */
                        else
                              base->lcdlight.current++;   /* target is brighter as current */
                  } else
                        base->lcdlight.current = base->lcdlight.target;
                  process_queue_single (CONFIGQUEUE, TAG_BACKLIGHTLEVEL, base->lcdlight.current);
                  display_framebuffer (base->lcdlight.current ? 1: 0);
            }
      }

      if (base->flags.lmu_enable)
            if (base->kbdlight.current != base->kbdlight.target) {
                  base->kbdlight.fadingcount++;
                  if (base->kbdlight.fadingcount >= base->kbdlight.fadingspeed) {
                        base->kbdlight.fadingcount = 0;
                        if (base->kbdlight.fadingspeed) {
                              if (base->kbdlight.current > base->kbdlight.target)
                                    base->kbdlight.current--;   /* target is darker as current */
                              else
                                    base->kbdlight.current++;   /* target is brighter as current */
                        } else
                              base->kbdlight.current = base->kbdlight.target;
                        process_queue_single (CONFIGQUEUE, TAG_KEYBLIGHTLEVEL, base->kbdlight.current);
                  }
            }
}

/* Timer function called every second
 * In this function the automatic brighness adjustments for
 * LCD and keyboard are done.
 * The equations to calculate the new values allow values
 * generated out of range. This doesn't matter as long as
 * the function display_set_lcdbrightness() clip them to the
 * valid range.
 */
void
display_ambienttimer (struct tagitem *taglist)
{
      struct moddata_display *base = &modbase_display;
      long ambient;
      int level, lcdmax, lcdmin, ac;

      if (base->flags.lmu_enable && base->flags.status == STATUS_NORMAL) {
            /* process this code only if a LMU is present and the display
             * is not dimmed or switched off
             */
            ac = process_queue_single (QUERYQUEUE, TAG_POWERSOURCE, 1);
            lcdmin = ac ? base->autoadj_min_ac : base->autoadj_min_bat; 
            lcdmax = ac ? base->autoadj_max_ac : base->autoadj_max_bat;
      
            if ((ambient = process_queue_single (QUERYQUEUE, TAG_AMBIENTLIGHT, -1)) > -1) {
                  if (base->flags.kbd_autoadjust && !base->flags.kbd_switchedoff) {
                        level = -base->kbdlight.max * ambient/base->kbdlight.threshold
                            + base->kbdlight.max;
                        if (level + base->kbdlight.offset > base->kbdlight.max)
                              base->kbdlight.offset = base->kbdlight.max - level;
                        if (level + base->kbdlight.offset < 1)
                              base->kbdlight.offset = -level;
                        level += base->kbdlight.offset; 
                        display_set_kbdbrightness(level);
                  }
                  
                  if (base->flags.lcd_autoadjust) {
                        level = (base->lcdlight.max * ambient/base->lcdlight.threshold) + 1;
                        if (level > lcdmax) level = lcdmax;
                        if (level < lcdmin) level = lcdmin;
                        if (level + base->lcdlight.offset > base->lcdlight.max)
                              base->lcdlight.offset = base->lcdlight.max - level;
                        if (level + base->lcdlight.offset < 1)
                              base->lcdlight.offset = -level + 1;
                        level += base->lcdlight.offset; /* offset due to manual adjustment */
                        display_set_lcdbrightness(level);
                  }
            }
      }
}

void
display_query (struct tagitem *taglist)
{
      display_handle_tags (MODE_QUERY, taglist);
}

void
display_configure (struct tagitem *taglist)
{
      display_handle_tags (MODE_CONFIG, taglist);
}

void
display_handle_tags (int cfgure, struct tagitem *taglist)
{
      struct moddata_display *base = &modbase_display;
      int err, level;

      while (taglist->tag != TAG_END) {
            switch (taglist->tag) {
            case TAG_BRIGHTNESSOP:  /* private tag */
                  if (cfgure) display_change_brightness (taglist->data);
                  break;
            case TAG_LCDBRIGHTNESS:
                  if (cfgure) {
                        level = display_set_lcdbrightness (taglist->data);
                        singletag_to_clients(CHANGEVALUE, TAG_LCDBRIGHTNESS, level);
                  } else
                        taglist->data = base->flags.nobacklight ? -1 : base->lcdlight.current;
                  break;
            case TAG_LCDBRIGHTNESSMAX:
                  if (cfgure) tagerror (taglist, E_NOWRITE);
                  else        taglist->data = base->lcdlight.max;
                  break;
            case TAG_LCDFADINGSPEED:
                  if (cfgure) base->lcdlight.fadingspeed = taglist->data;
                  else        taglist->data = base->lcdlight.fadingspeed;
                  break;
            case TAG_KBDBRIGHTNESS:
                  if (cfgure) {
                        if ((level = display_set_kbdbrightness (taglist->data)) > 0)
                              base->flags.kbd_switchedoff = 0;
                        singletag_to_clients(CHANGEVALUE, TAG_KBDBRIGHTNESS, level);
                  } else
                        taglist->data = base->kbdlight.current;
                  break;
            case TAG_KBDONBRIGHTNESS:
                  if (cfgure) {
                        level = taglist->data;
                        if (level < KBD_BRIGHTNESS_MIN)
                              level = KBD_BRIGHTNESS_MIN;
                        else if (level > base->kbdlight.max)
                              level = base->kbdlight.max;
                        base->kbdon_brightness = level;
                  } else
                        taglist->data = base->kbdon_brightness;
                  break;
            case TAG_KBDBRIGHTNESSMAX:
                  if (cfgure) tagerror (taglist, E_NOWRITE);
                  else        taglist->data = base->kbdlight.max;
                  break;
            case TAG_KBDFADINGSPEED:
                  if (cfgure) base->kbdlight.fadingspeed = taglist->data;
                  else        taglist->data = base->kbdlight.fadingspeed;
                  break;
            case TAG_LCDILLUMUPKEY:
                  if (cfgure) base->keylcdup = taglist->data;
                  else        taglist->data = base->keylcdup;
                  break;
            case TAG_LCDILLUMUPMOD:
                  if (cfgure) base->modlcdup = taglist->data;
                  else        taglist->data = base->modlcdup;
                  break;
            case TAG_LCDILLUMDOWNKEY:
                  if (cfgure) base->keylcddn = taglist->data;
                  else        taglist->data = base->keylcddn;
                  break;
            case TAG_LCDILLUMDOWNMOD:
                  if (cfgure) base->modlcddn = taglist->data;
                  else        taglist->data = base->modlcddn;
                  break;
            case TAG_KBDILLUMUPKEY:
                  if (cfgure) base->keykbdup = taglist->data;
                  else        taglist->data = base->keykbdup;
                  break;
            case TAG_KBDILLUMUPMOD:
                  if (cfgure) base->modkbdup = taglist->data;
                  else        taglist->data = base->modkbdup;
                  break;
            case TAG_KBDILLUMDOWNKEY:
                  if (cfgure) base->keykbddn = taglist->data;
                  else        taglist->data = base->keykbddn;
                  break;
            case TAG_KBDILLUMDOWNMOD:
                  if (cfgure) base->modkbddn = taglist->data;
                  else        taglist->data = base->modkbddn;
                  break;
            case TAG_KBDILLUMONKEY:
                  if (cfgure) base->keykbdon = taglist->data;
                  else        taglist->data = base->keykbdon;
                  break;
            case TAG_KBDILLUMONMOD:
                  if (cfgure) base->modkbdon = taglist->data;
                  else        taglist->data = base->modkbdon;
                  break;
            case TAG_CRTMIRRORKEY:
                  if (cfgure) base->keymirror = taglist->data;
                  else        taglist->data = base->keymirror;
                  break;
            case TAG_CRTMIRRORMOD:
                  if (cfgure) base->modmirror = taglist->data;
                  else        taglist->data = base->modmirror;
                  break;
            case TAG_FRAMEBUFFERDEVICE:
                  if (cfgure) {
                        if ((err = copy_path ((char *) taglist->data, base->fbdev, TYPE_CHARDEV, CPFLG_NONE)))
                              tagerror (taglist, err);
                  } else
                        taglist->data = (long) base->fbdev;
                  break;
            case TAG_BLANKFRAMEBUFFER:
                  if (cfgure) base->flags.ctrl_fb = taglist->data & 1;
                  else        taglist->data = base->flags.ctrl_fb;
                  break;
            case TAG_DIMFULLYDARK:
                  if (cfgure) base->flags.dimfullydark = taglist->data & 1;
                  else        taglist->data = base->flags.dimfullydark;
                  break;
            case TAG_LCDAUTOADJUST:
                  if (cfgure) {
                        base->flags.lcd_autoadjust = taglist->data & 1;
                        base->lcdlight.offset = 0;
                  } else
                        taglist->data = base->flags.lcd_autoadjust;
                  break;
            case TAG_KBDAUTOADJUST:
                  if (cfgure) {
                        base->flags.kbd_autoadjust = taglist->data & 1;
                        base->kbdlight.offset = 0;
                  } else
                        taglist->data = base->flags.kbd_autoadjust;
                  break;
            case TAG_KBDTHRESHOLD:
                  if (cfgure) {
                        if (taglist->data > 99)
                              base->kbdlight.threshold = 99;
                        else if (taglist->data < 1)
                              base->kbdlight.threshold = 1;
                        else
                              base->kbdlight.threshold = taglist->data;
                  } else
                        taglist->data = base->kbdlight.threshold;
                  break;
            case TAG_LCDTHRESHOLD:
                  if (cfgure) {
                        if (taglist->data > 99)
                              base->lcdlight.threshold = 99;
                        else if (taglist->data < 1)
                              base->lcdlight.threshold = 1;
                        else
                              base->lcdlight.threshold = taglist->data;
                  } else
                        taglist->data = base->lcdlight.threshold;
                  break;
            case TAG_LCDAUTOADJMINBAT:
                  if (cfgure) base->autoadj_min_bat = taglist->data;
                  else        taglist->data = base->autoadj_min_bat;
                  break;
            case TAG_LCDAUTOADJMAXBAT:
                  if (cfgure) base->autoadj_max_bat = taglist->data;
                  else        taglist->data = base->autoadj_max_bat;
                  break;
            case TAG_LCDAUTOADJMINAC:
                  if (cfgure) base->autoadj_min_ac = taglist->data;
                  else        taglist->data = base->autoadj_min_ac;
                  break;
            case TAG_LCDAUTOADJMAXAC:
                  if (cfgure) base->autoadj_max_ac = taglist->data;
                  else        taglist->data = base->autoadj_max_ac;
                  break;
            case TAG_COVERSTATUS:      /* private tag */
                  if (cfgure) base->flags.coveropen = taglist->data & 1;
                  break;
            case TAG_PREPAREFORSLEEP:  /* private tag */
                  if ((cfgure) && base->flags.nobacklight) {
                        display_framebuffer (0);
                  }
                  break;
            case TAG_WAKEUPFROMSLEEP:  /* private tag */
                  if ((cfgure) && base->lcdlight.current) {
                        display_framebuffer (1);
                  }
                  /* base->coveropen must be synchronized after sleep. This is done
                   * by the module_pmac. This module sends the WAKEUPFROMSLEEP tag
                   * and after a short delay the COVERSTATUS tag so that no special
                   * actions need to be taken here.
                   */
                  break;
            }
            taglist++;
      }
}

/* This functions checks the limits of a given brightness level,
 * clip it if neseccary and set it as new target.
 */
int
display_set_lcdbrightness(int level)
{
      struct moddata_display *base = &modbase_display;
      
      if (base->flags.nobacklight) {
            if (level > 0) level = base->lcdlight.max;
            base->lcdlight.target = level;
            return -1;
      } else
            return display_clip_brightness (&base->lcdlight, level);
}

int
display_set_kbdbrightness(int level)
{
      struct moddata_display *base = &modbase_display;
      return display_clip_brightness (&base->kbdlight, level);
}

int
display_clip_brightness(struct display_light *illu, int level)
{
      if (level > illu->max)
            level = illu->max;
      if (level < 0)
            level = 0;
      illu->target = level;
      return level;
}

/* central control function for LCD backlight and keyboard
 * illumination interface to the outer world. Up to now only
 * module_powersave.c called this function.
 * status of the machine:
 *   0: normal operation, LCD on, KBD on
 *   1: dimmed, LCD min or off, KBD off
 *   2: off, LCD off, KBD off
 * The brightness level will be set by the display_timer()
 * function.
 */
void
display_change_brightness(int op)
{
      struct moddata_display *base = &modbase_display;

      /* somebody might have changed the brightness level directly so
       * check if we are still synchron here
       */
      display_sync_lcdbrightness ();
      
      if (((op == OP_DIM_RECOVER) && (base->flags.status == STATUS_NORMAL)) ||
           ((op == OP_DIM_LIGHT) && (base->flags.status != STATUS_NORMAL)) ||
           ((op == OP_DIM_OFF) && (base->flags.status == STATUS_OFF)))
            return;

      /* if a backlight controller is not available try to dim to
       * complete darkness in hope the framebuffer device is able
       * to switch the backlight off. The framebuffer option must
       * be configured accordingly to make this work.
       */
      if ((base->flags.dimfullydark || base->flags.nobacklight) && op == OP_DIM_LIGHT)
            op = OP_DIM_OFF;

      switch (op) {
      case OP_DIM_LIGHT:
            base->lcdlight.backup = base->lcdlight.current;
            /* if current LCD brightness level is 0 then let it
             *  as it is because it is user's will */
            if (base->lcdlight.current > LCD_BRIGHTNESS_OFF)
                  base->lcdlight.target = LCD_BRIGHTNESS_MIN;
            base->kbdlight.backup = base->kbdlight.current;
            base->kbdlight.target = KBD_BRIGHTNESS_OFF;
            base->flags.status = STATUS_DIMMED;
            break;
      case OP_DIM_OFF:
            if (base->flags.status != STATUS_DIMMED) {
                  base->lcdlight.backup = base->lcdlight.current;
                  base->kbdlight.backup = base->kbdlight.current;
            }
            base->lcdlight.target = LCD_BRIGHTNESS_OFF;
            base->kbdlight.target = KBD_BRIGHTNESS_OFF;
            base->flags.status = STATUS_OFF;
            break;
      case OP_DIM_RECOVER:
            base->lcdlight.target = base->lcdlight.backup;
            /* don't recover zero display brightness
             * set to minimum brightness instead */
            if (base->lcdlight.target == LCD_BRIGHTNESS_OFF)
                  base->lcdlight.target = LCD_BRIGHTNESS_MIN;
            base->kbdlight.target = base->kbdlight.backup;
            base->flags.status = STATUS_NORMAL;
            break;
      }
}

void
display_framebuffer (int on)
{
      struct moddata_display *base = &modbase_display;
      int fd = -1, err;

      if (base->flags.ctrl_fb) {
            if ((fd = open(base->fbdev, O_RDWR)) >= 0) {    /* open framebuffer device */
                  err = ioctl(fd, FBIOBLANK, on ? 0 : VESA_POWERDOWN + 1);
//                print_msg (PBB_INFO, "Framebuffer on: %d, error: %d\n", !on, err);
                  close (fd);
            } else
                  print_msg (PBB_ERR, _("Can't open framebuffer device '%s'.\n"), base->fbdev);
      }
}

void
display_sync_lcdbrightness (void)
{
      struct moddata_display *base = &modbase_display;
      int level;

      level = process_queue_single (QUERYQUEUE, TAG_BACKLIGHTLEVEL, -1);
      if (level != base->lcdlight.current) {
            base->flags.status = STATUS_NORMAL;
            if (level != -1) {
                  /* Somebody else has changed the LCD brightness
                   * so sync our system. */
                  base->lcdlight.current  = level;
                  base->lcdlight.target   = level;
                  base->flags.nobacklight = 0;
            } else {
                  /* no backlight controller available */
                  base->lcdlight.current  = base->lcdlight.max;
                  base->lcdlight.target   = base->lcdlight.max;
                  base->flags.nobacklight = 1;
            }
      }
}

int
display_switchmirror ()
{
      struct moddata_display *base = &modbase_display;
      unsigned long value;
      int fd, rc = -1;
      
      if ((fd = open(base->fbdev, O_RDWR)) >= 0) {    /* open framebuffer device */
            if (ioctl(fd, FBIO_ATY128_GET_MIRROR, &value) == 0) {
                  value ^= ATY_MIRROR_CRT_ON;
                  ioctl(fd, FBIO_ATY128_SET_MIRROR, &value);
                  rc = value & ATY_MIRROR_CRT_ON ? 1 : 0;
            } else if (ioctl(fd, FBIO_RADEON_GET_MIRROR, &value) == 0) {
                  value ^= ATY_RADEON_CRT_ON;
                  ioctl(fd, FBIO_RADEON_SET_MIRROR, &value);
                  rc = value & ATY_RADEON_CRT_ON ? 1 : 0;
            }                       
            close (fd);
      } else
            print_msg (PBB_ERR, _("Can't open framebuffer device '%s'.\n"), base->fbdev);
      return rc;
}


Generated by  Doxygen 1.6.0   Back to index