/****************************************************************************
**
** Copyright (C) 2000-2006 TROLLTECH ASA. All rights reserved.
**
** This file is part of the Phone Edition of the Qtopia Toolkit.
**
** This software is licensed under the terms of the GNU General Public
** License (GPL) version 2.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "htcbuthandler.h"

//#ifdef QT_QWS_PXA27X
#include <QFile>
#include <QTextStream>
#include <QScreen>
#include <QSocketNotifier>
#include <QDebug>
#include <QStringList>

#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

// #define OK_BUTTON  28
// #define IE_BUTTON  150
// #define WIN_BUTTON 139
// #define CAM_BUTTON 212
// #define REC_BUTTON 167
// #define JOG_DOWN   114
// #define JOG_UP     115
// #define PWR_BUTTON 116
// #define PAD_UP     103
// #define PAD_RIGHT  87
// #define PAD_DOWN   108
// #define PAD_LEFT   105
// #define PHONE_CALL  65
// #define PHONE_HANGUP  66
// #define CONTACT_KEY   63
// #define CALENDAR_KEY  64

#define OK_BUTTON 	28	//KEY_ENTER
#define PAD_LEFT	105	//KEY_LEFT
#define PAD_RIGHT	106	//KEY_RIGHT
#define PAD_UP		103	//KEY_UP
#define PAD_DOWN	108	//KEY_DOWN
#define CALENDER_KEY	67	//KEY_F9
#define CONTACT_KEY  	68	//KEY_F10
#define GPS_KEY		87	//KEY_F11
#define CLOCK_KEY	88	//KEY_F12
#define RECORD_KEY	89	//KEY_RO

htcButHandler::htcButHandler(const QString &device)
{
    setObjectName( "HTC buttons Handler" );
    devName = device;
    setEnvDevice(devName);

    shift=false;
}

htcButHandler::~htcButHandler()
{
}

int htcButHandler::setDevice(const QString& device, const QString& mode)
{
//     qDebug() << device << mode;
	if (mode == QString("ASIC3"))
	{
		Asic3FD = ::open(device.toLocal8Bit().constData(), O_RDONLY, 0);
		if (Asic3FD >= 0) {
			//qWarning("Opened event1 as button ASIC3 input");
			m_notify = new QSocketNotifier( Asic3FD, QSocketNotifier::Read, this );
			connect( m_notify, SIGNAL(activated(int)), this, SLOT(readAsic3Keys()));
		} else {
			qWarning("Cannot open %s for ASIC3 buttons (%s)", devName.toLocal8Bit().constData(), strerror(errno));
			return 1;
		}
	}
	if (mode == QString("GPIO"))
	{
		GpioFD = ::open(device.toLocal8Bit().constData(), O_RDONLY, 0);
		if (GpioFD >= 0) {
			//qWarning("Opened event0 as button GPIO input");
			m_notify = new QSocketNotifier( GpioFD, QSocketNotifier::Read, this );
			connect( m_notify, SIGNAL(activated(int)), this, SLOT(readGpioKeys()));
		} else {
			qWarning("Cannot open %s for GPIO buttons (%s)", devName.toLocal8Bit().constData(), strerror(errno));
			return 1;
		}
	}
	if (mode == QString("EXT"))
	{
	ExtFD = ::open(device.toLocal8Bit().constData(), O_RDONLY, 0);
	if (ExtFD >= 0) {
		//qWarning("Opened event0 as button GPIO input");
		m_notify = new QSocketNotifier( ExtFD, QSocketNotifier::Read, this );
		connect( m_notify, SIGNAL(activated(int)), this, SLOT(readExtKeys()));
	} else {
		qWarning("Cannot open %s for GPIO buttons (%s)", devName.toLocal8Bit().constData(), strerror(errno));
		return 1;
	}
	}

   return 0;
}
/* TSDogs: added this to detect from environment          */
/* this is duplicate checking as qtopiacore has this info */
/* but does not pass it by to external plugins (?)        */

int htcButHandler::setEnvDevice(const QString &keys)
{
  QStringList *keyboard;
  keyboard = new QStringList(keys);

/* this should never happen, as then how were we called */
  if (keyboard->isEmpty())
     return 1;

  QString device;
  QString type;
  QString mode;
  for (int i = keyboard->size() - 1; i >= 0; --i) {
     const QString spec = keyboard->at(i);
     qWarning( "device to use : %s ", spec.toLocal8Bit().constData());
		QStringList devices = spec.split(QLatin1Char(':'));
		for (int j = devices.size() - 1; j >= 0; --j) {
			const QString event = devices.at(j);
			int param1 = event.indexOf(QLatin1Char(','));
			mode = event.mid(param1+1);
			device = event.left(param1);
			qWarning("Set device %s to handle %s", device.toLocal8Bit().constData(), mode.toLocal8Bit().constData());
			if (setDevice( device, mode)) {
				qWarning("Leave with error");
				return 1;
			}
		}
   }
  return 0;
}

void htcButHandler::readGpioKeys()
{
    htcInput event;

    int n = read(GpioFD, &event, sizeof(htcInput));
    if(n !=16) {
      qWarning("keypressed on GPIO: n=%03d",n);
      return;
    }
    processEvent(event);
}

void htcButHandler::readAsic3Keys()
{
    htcInput event;

    int n = read(Asic3FD, &event, sizeof(htcInput));
    if(n !=16) {
      qWarning("keypressed on ASIC3: n=%03d",n);
      return;
    }
    processEvent(event);

}

void htcButHandler::readExtKeys()
{
    htcInput event;

    int n = read(ExtFD, &event, sizeof(htcInput));
    if(n !=16) {
      qWarning("keypressed on EXT: n=%03d",n);
      return;
    }
    processEvent(event);

}

void htcButHandler::processEvent(htcInput event)
{
    int modifiers=0;
    int unicode=0xffff;
    int key_code=0;


    switch(event.code)
    {
	case OK_BUTTON:
		key_code = Qt::Key_Select;
		unicode  = 0xffff;
		break;
	case PAD_LEFT:
		key_code = Qt::Key_Left;
		unicode  = 0xffff;
		break;
	case PAD_RIGHT:
		key_code = Qt::Key_Right;
		unicode  = 0xffff;
		break;
	case PAD_UP:
		key_code = Qt::Key_Up;
		unicode  = 0xffff;
		break;
	case PAD_DOWN:
		key_code = Qt::Key_Down;
		unicode  = 0xffff;
		break;
	case CALENDER_KEY:
		key_code = Qt::Key_F9;
		unicode  = 0xffff;
		break;
	case CONTACT_KEY:
		key_code = Qt::Key_F10;
		unicode  = 0xffff;
		break;
	case GPS_KEY:
		key_code = Qt::Key_F11;
		unicode  = 0xffff;
		break;
	case CLOCK_KEY:
		key_code = Qt::Key_F12;
		unicode  = 0xffff;
		break;
	case RECORD_KEY:
		key_code = Qt::Key_Bar;
		unicode  = 0xffff;
		break;
    }
    if(shift) modifiers |= Qt::ShiftModifier;

    processKeyEvent(unicode, key_code, (Qt::KeyboardModifiers)modifiers, event.value!=0, false);
//     qWarning("keypressed: type=%03d, code=%03d, value=%03d (%s)",event.type, event.code,event.value,((event.value)!=0) ? "Down":"Up");

}
//#endif // QT_QWS_PXA27X
