pikeyd165 – Rev 1

Subversion Repositories:
Rev:
/**** config.c *****************************/
/* M. Moller   2013-01-16                  */
/*   Universal RPi GPIO keyboard daemon    */
/*******************************************/

/*
   Copyright (C) 2013 Michael Moller.
   This file is part of the Universal Raspberry Pi GPIO keyboard daemon.

   This is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The software 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"

#define NUM_GPIO 32
#define MAX_LN 128


extern key_names_s key_names[];


key_special_s KEY_SPECIAL[20];





typedef struct _gpio_key{
  int gpio;
  int idx;
  int key;
  struct _gpio_key *next;
}gpio_key_s;


static int find_key(const char *name);
static void add_event(gpio_key_s **ev, int gpio, int key);
static gpio_key_s *get_event(gpio_key_s *ev, int idx);

static gpio_key_s *gpio_key[NUM_GPIO];
static gpio_key_s *last_gpio_key = NULL;
static int gpios[NUM_GPIO];
static int num_gpios_used=0;

static int SP;

#define SET_BIT(var,pos) ((var) | (1<<(pos)))

int init_config(void)
{
  int i,k,n;
  FILE *fp;
  char ln[MAX_LN];
  char name[32];
  char conffile[80];
  int gpio;
  int idx;
  int a,b,c,d,e;
  
  for(i=0;i<NUM_GPIO;i++){
    gpio_key[i] = NULL;
  }

  /* search for the conf file in ~/.piked.conf and /etc/pikeyd165.conf */
  sprintf(conffile, "%s/.pikeyd165.conf", getenv("HOME"));
  fp = fopen(conffile, "r");
  if(!fp){
    fp = fopen("/etc/pikeyd165.conf", "r");
    if(!fp){
      perror(conffile);
      perror("/etc/pikeyd165.conf");
    }
    sprintf(conffile, "/etc/pikeyd165.conf");
  }
  if(fp){
    printf("Config file is %s\n", conffile);
  }

  idx=0;
  while(fp && !feof(fp)){
    if(fgets(ln, MAX_LN, fp)){
      if(strlen(ln) > 1){
        if(ln[0]=='#')continue;
        a=b=c=d=e=-1;
        n=sscanf(ln, "%s %d %d %d %d %d", name, &gpio, &b, &c, &d, &e);
        if(n>1){
          k = find_key(name);
          if(k){
            if(n==2)
              {
               //printf("[%s] = %d (%d)\n",name, gpio, key_names[k].code);
               SP=0;
               add_event(&gpio_key[gpio], gpio, key_names[k].code);
              }
            else
              {
                a=gpio;
                //printf("%i %i %i %i %i\n",a,b,c,d,e);
                KEY_SPECIAL[idx].pressed=0;
                KEY_SPECIAL[idx].key=k;
                if(a>0) KEY_SPECIAL[idx].bits |= 1 << a;
                if(b>0) KEY_SPECIAL[idx].bits |= 1 << b;
                if(c>0) KEY_SPECIAL[idx].bits |= 1 << c;
                if(d>0) KEY_SPECIAL[idx].bits |= 1 << d;
                if(e>0) KEY_SPECIAL[idx].bits |= 1 << e;                                                                                    

                idx++;
              }
             }
          }
        }
      }
    }
 
  KEY_SPECIAL[idx].key=0;
  KEY_SPECIAL[idx].bits=0;


  for(idx=0; KEY_SPECIAL[idx].key!=0 && KEY_SPECIAL[idx].bits!=0 ; idx++)
   {
     printf("%i %08x\n", KEY_SPECIAL[idx].key,KEY_SPECIAL[idx].bits);
   }
  
  if(fp){
    fclose(fp);
  }

  n=0;
  for(i=0; i<NUM_GPIO; i++){
    if(gpio_key[i]){
      gpios[n] = gpio_key[i]->gpio;
      n++;
    }
  }
  num_gpios_used = n;

  return 0;
}

static int find_key(const char *name)
{
  int i=0;
  while(key_names[i].code >= 0){
    if(!strncmp(key_names[i].name, name, 32))break;
    i++;
  }
  return i;
}

static void add_event(gpio_key_s **ev, int gpio, int key)
{
  if(*ev){
    SP++;
    /* Recursive call to add the next link in the list */
    add_event(&(*ev)->next, gpio, key);
  }
  else{
    *ev = malloc(sizeof(gpio_key_s));
    if(*ev==NULL){
      perror("malloc");
    }
    else{
      (*ev)->gpio = gpio;
      (*ev)->idx = SP;
      (*ev)->key = key;
      (*ev)->next = NULL;
    }
  }
}

static gpio_key_s *get_event(gpio_key_s *ev, int idx)
{
  if(ev->idx == idx){
    return ev;
  }
  else if(!ev->next){
    return NULL;
  }
  else{
    return get_event(ev->next, idx);
  }
}

int get_event_key(int gpio, int idx)
{
  gpio_key_s *ev;
  ev = get_event(gpio_key[gpio], idx);
  if(ev){
    return ev->key;
  }
  else{
    return 0;
  }
}

int got_more_keys(int gpio)
{
  if( last_gpio_key == NULL ){
    return (gpio_key[gpio] != NULL);
  }
  else if( last_gpio_key->next == NULL){
    return 0;
  }
  else{
    return 1;
  }
}

void restart_keys(void)
{
    last_gpio_key = NULL;
}

int get_next_key(int gpio)
{
  static int lastgpio=-1;
  static int idx = 0;
  gpio_key_s *ev;
  int k;

  ev = last_gpio_key;
  if( (ev == NULL) || (gpio != lastgpio) ){
    /* restart at the beginning after reaching the end, or reading a new gpio */
    ev = gpio_key[gpio];
    lastgpio = gpio;
  }
  else{
    /* get successive events while retrieving the same gpio */
    ev = last_gpio_key->next;
  }
  last_gpio_key = ev;

  if(ev){
    k = ev->key;
  }
  else{
    k = 0;
  }
  return k;
}

void test_config(void)
{
  int e, i, k;
  e=21;

  for(i=0; i<NUM_GPIO; i++){
    if(gpio_key[i]){
      printf(" %d\n", i);
    }
  }

  while( got_more_keys(e) ){
    k = get_next_key(e);
    printf("%d: EV %d = %d\n", i++, e, k);
    if(i>8)break;
  }
  i=0;
  restart_keys();
  while( got_more_keys(e) ){
    k = get_next_key(e);
    printf("%d: EV %d = %d\n", i++, e, k);
    if(i>8)break;
  }
}

int gpios_used(void)
{
  return num_gpios_used;
}

int gpio_pin(int n)
{
  return gpios[n % NUM_GPIO];
}