

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>

#include "lirc.h"
#include "extb_lircwatch.h"

#include <vdr/tools.h>

#define REPEATLIMIT  20 // ms
#define REPEATDELAY 350 // ms
#define KEYPRESSDELAY 150 // ms

cExtBLircWatch::cExtBLircWatch(const char *DeviceName)
: m_bShutdown(false)
{
  struct sockaddr_un addr;
  addr.sun_family = AF_UNIX;
  strncpy(addr.sun_path, DeviceName, sizeof(addr.sun_path));
  if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
    if (connect(m_fd, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
	    dsyslog("extb: cExtBLircWatch::open(fd=%d)", m_fd);
      Start();
      return;
    }
    esyslog("extb: cExtBLircWatch: could not connect to socket: %s",strerror(errno));
  }
  else
    {
    esyslog("extb: cExtBLircWatch: could not open socket: %s", strerror(errno));
    }
  close();
}

cExtBLircWatch::~cExtBLircWatch()
{
  m_bShutdown = true;
  close();
  Cancel();
}

void cExtBLircWatch::close()
{
  if(-1 == m_fd) {
	    dsyslog("extb: cExtBLircWatch::close(fd=%d)", m_fd);
	    ::close(m_fd);
	    m_fd = -1;
	}
}

void cExtBLircWatch::StartWatch()
{
  watch = true;
  watch_success = false;
  video_modes = 0;
  scart_boot_modes = 0;
  video_found = false;
  scart_boot_found = false;
}

void cExtBLircWatch::Action(void)
{
  dsyslog("extb: cExtBLircWatch thread started (pid=%d)", getpid());

  char buf[LIRC_BUFFER_SIZE];
  int timeout = -1;

  for (; m_fd >= 0 && !m_bShutdown;) {
    
    LOCK_THREAD;
    
    bool ready = cFile::FileReady(m_fd, timeout);
    int ret = ready ? safe_read(m_fd, buf, sizeof(buf)) : -1;

    if(m_bShutdown)
      break;
    if (ready && ret <= 0 ) {
      esyslog("extb: cExtBLircWatch::Action connection lost");
      close();
      break;
    }
    
    if (ready && ret > 21) {
      char KeyName[LIRC_KEY_BUF];
      char Remote[256];
      sscanf(buf, "%*x %*x %29s %s", KeyName, Remote); // '29' in '%29s' is LIRC_KEY_BUF-1!
    
      moredsyslog("extb: cExtBLircWatch: %s / %s", KeyName, Remote);
    
      if(watch && 0 == strncmp("EXTB_RX", Remote,7)) {
        moredsyslog("extb: checking key: >%s<", KeyName);
        
        if(0 == strncmp(KeyName, "V", 1)) {
          dsyslog("extb: video mode found");
          video_modes = atoi(&KeyName[1]);
          video_found = true;
        }
        
        if(0 == strncmp(KeyName, "SB", 2)) {
          dsyslog("extb: scart boot mode found");
          sscanf(&KeyName[2], "%x", &scart_boot_modes);
          scart_boot_found = true;
        }
      
        if(video_found && scart_boot_found) {
            dsyslog("extb: answer from extb complete");
            watch_success = true;
        }
      }
    }
  }
  dsyslog("extb: cExtBLircWatch thread closed (pid=%d)", getpid());
}
