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

kbd.c

/*
 * fbgetty : a getty for framebuffer 
 * Copyright (C) 2001 Yann Droneaud <ydroneaud@meuh.eu.org>. 
 *
 * fbgetty 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, or (at your option)
 * any later version.
 *
 * fbgetty is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 *
 */

#include <fbgetty/global.h>
#include <fbgetty/options.h>

#include <stdlib.h>
#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <sys/ioctl.h>

#include <fbgetty/kbd.h>
#include <fbgetty/errors.h>

struct opt
{
  char *name;
  unsigned char value;
}
leds_opts[] =
{
  { "num" ,      FBGETTY_LEDS_NUM },  { "numlock",   FBGETTY_LEDS_NUM },
  { "caps" ,     FBGETTY_LEDS_CAPS }, { "capslock" , FBGETTY_LEDS_CAPS },
  { NULL, 0 }
};

#define FBGETTY_KBD_LEDS_UNSET_SHIFT 0x08
#define FBGETTY_KBD_LEDS_MASK        ((0x01 << FBGETTY_KBD_LEDS_UNSET_SHIFT) - 1)

#define FBGETTY_KBD_LEDS(unset, set) ((unset << FBGETTY_KBD_LEDS_UNSET_SHIFT) | set)
#define FBGETTY_KBD_LEDS_SET(leds)   (leds & FBGETTY_KBD_LEDS_MASK)
#define FBGETTY_KBD_LEDS_UNSET(leds) (leds >> FBGETTY_KBD_LEDS_UNSET_SHIFT)

/* parse a string in form "+num,num,-num" */
int
leds_parse(const char *str, unsigned int *mask)
{
  int opt_index;

  char *cp;
  char *name;

  /* set the default value */
  unsigned int setleds = 0;
  unsigned int unsetleds = 0;
  unsigned char set;

  char *tokens = " ,";

  cp = strdup(str);
  if (cp == NULL)
    return(-1);

  name = strtok(cp, tokens);

  while(name != NULL)
    {
      set = 1; /* by default set the flag */
      switch(*name)
      {
      case '-':
        set = 0;
      case '+':
        name++;
        break;
      }

      /* look up the flags table */
      for (opt_index = 0; leds_opts[opt_index].name != NULL; opt_index++)
      {
        if (strcmp(leds_opts[opt_index].name, name) == 0)
          {
            if (set == 0)
            unsetleds |= leds_opts[opt_index].value;
            else
            setleds |= leds_opts[opt_index].value;

            goto found;
          }
      }

      free(cp);
      /* not found */
      return(-1);

    found:
      name = strtok(NULL, tokens);
    }

  free(cp);

  *mask = FBGETTY_KBD_LEDS(unsetleds,setleds);

  return(0);
}

/*
 * kbd_opt: set/reset flags
 */
int
kbd_opt(int mode, unsigned int mask)
{
#ifdef __linux__
  unsigned char current_flags;
  unsigned char fullmask;

  if (ioctl(STDIN_FILENO, KDGKBLED, &current_flags) == -1)
    return(-1);

  mask &= 0x00000007;

  fullmask = (unsigned char) ((mask << 4) | mask);

  switch(mode)
    {
    case FBGETTY_KBD_SET:
      current_flags |= fullmask;
      break;
    case FBGETTY_KBD_UNSET:
      current_flags &= ~fullmask;
      break;

    default:
      return(0);
    }

  return(ioctl(STDIN_FILENO, KDSKBLED, current_flags));

#else

  return -1;

#endif /* __linux__ */
}


/*
 * set or clear kbd flags according to fgoptions->leds
 */
int
init_kbd(void)
{
  unsigned int unset;
  unsigned int set;

  /* only init kbd when there somethings to change */

  if (fgoptions->leds != 0)
    {
      unset = FBGETTY_KBD_LEDS_UNSET(fgoptions->leds);
      set = FBGETTY_KBD_LEDS_SET(fgoptions->leds);

      /* set the leds */
#ifdef FB_GETTY_DEBUG
      error("unsetleds = 0x%02x", unset); 
      error("setleds = 0x%02x", set);
#endif
      
      if (unset != 0)
      {
        if (kbd_opt(FBGETTY_KBD_UNSET, FBGETTY_KBD_LEDS_UNSET(fgoptions->leds)) == -1)
          {
            error("keyboard unset failed");
            return(-1);
          }
      }      

      if (set != 0)
      {
        if (kbd_opt(FBGETTY_KBD_SET, FBGETTY_KBD_LEDS_SET(fgoptions->leds)) == -1)
          {
            error("keyboard set failed");
            return(-1);
          }
      }
    }
#ifdef FB_GETTY_DEBUG
  else
    {
      error("no kbd settings");
    }
#endif
 
  return(0);
}

Generated by  Doxygen 1.6.0   Back to index