/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License 
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public 
 * License as published by the Free Software Foundation.
 *
 * This program 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 https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> 
#include <netdb.h>
#include <directfb.h>
#include <directfb_keyboard.h>

#define TAGNAME  "DFBNetEvt-R1"
struct netevnet_packet
{
	char tag[16]; /* should be TAGNAME*/
	DFBInputEvent evt;
};


int main (int argc, char *argv[])
{
   int sock,          /* socket descriptor */
       val,           /* scratch variable */
       cnt;           /* number of bytes I/O */

   char key;
   int mtk_sym=1; //mtk tv control key symbols
 
   struct sockaddr_in mtnet_addr;  /* Internet socket name (addr) */
   struct sockaddr_in *nptr;   /* pointer to get port number */
 
   struct netevnet_packet pkt;   /* I/O buffer, kind of small  */
 
   struct hostent *hp, *gethostbyaddr();

   printf("usage: mtnetkb [host|ip(127.0.0.1)] [port(3579)]\n");
 
   if (( sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
      printf("socket fail=%d\n", errno);
      perror("mtnetkb");
      exit(2);
   }
  
   if(argc<3)
	mtnet_addr.sin_port = htons(3579); //0xdfb
   else
	mtnet_addr.sin_port = htons( atoi(argv[2]) ); 
   mtnet_addr.sin_family = AF_INET;
   if(argc<2)
	hp = gethostbyname ("127.0.0.1");
   else
   	hp = gethostbyname ( argv[1] );
 
   if ( hp == NULL ) {
      printf("mtnetkb gethostbyname fail=%d\n", errno);
      perror("mtnetkb");
      close ( sock );
      exit(3);
   }
 
   bcopy ( hp -> h_addr_list[0], &mtnet_addr.sin_addr.s_addr,
           hp -> h_length );

   /* Establish socket connection with (remote) server.  */
 
   if ( ( connect ( sock, &mtnet_addr, sizeof(mtnet_addr) ) ) < 0 ) {
         printf("mtnetkb %s connect fail=%d\n", argv[0], errno);
         perror("mtnetkb");
         close (sock);
         exit(4);
      }
   
   while(1)
   {
another_key:
	bzero  ( &pkt,    sizeof( pkt) );
	strcpy ( pkt.tag, TAGNAME );
	pkt.evt.type       = DIET_KEYPRESS ;
	pkt.evt.flags      = DIEF_KEYSYMBOL; /*|DIEF_KEYCODE */;
     
   	printf("Enter key:\n");
	key=(char)getchar();
	switch(key)
	{
	case '?': mtk_sym^=1; 
	default: goto another_key;
	case 'Q': goto leave;
	
	case '0': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_0:DIKS_0;break;
	case '1': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_1:DIKS_1;break;
	case '2': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_2:DIKS_2;break;
	case '3': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_3:DIKS_3;break;
	case '4': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_4:DIKS_4;break;
	case '5': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_5:DIKS_5;break;
	case '6': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_6:DIKS_6;break;
	case '7': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_7:DIKS_7;break;
	case '8': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_8:DIKS_8;break;
	case '9': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_9:DIKS_9;break;	
	case '.': pkt.evt.key_symbol=mtk_sym?DFB_BTN_DIGIT_DOT:DIKS_PERIOD;break;
	case '>': pkt.evt.key_symbol=mtk_sym?DFB_BTN_VOL_UP:DIKS_GREATER_THAN_SIGN;break;
	case '<': pkt.evt.key_symbol=mtk_sym?DFB_BTN_VOL_DOWN:DIKS_LESS_THAN_SIGN;break;
	case '+': pkt.evt.key_symbol=mtk_sym?DFB_BTN_PRG_UP:DIKS_PLUS_SIGN;break;
	case '-': pkt.evt.key_symbol=mtk_sym?DFB_BTN_PRG_DOWN:DIKS_MINUS_SIGN;break;
	case '!':pkt.evt.key_symbol=mtk_sym?DFB_BTN_PREV_PRG:DIKS_PREVIOUS;break;		
/*	case '\r':
	case '\n': */
	case ' ': /* use space resent enter */
		pkt.evt.key_symbol=mtk_sym?DFB_BTN_ENTER:DIKS_RETURN;break;	
	case 'I': pkt.evt.key_symbol=mtk_sym?DFB_BTN_INPUT_SRC:DIKS_MODE;break;
	case 'P':pkt.evt.key_symbol=mtk_sym?DFB_BTN_POWER:DIKS_POWER;break;
	case 'C':pkt.evt.key_symbol=mtk_sym?DFB_BTN_CLEAR:DIKS_CLEAR;break;	
	case 'S': pkt.evt.key_symbol=mtk_sym?DFB_BTN_SELECT:DIKS_SELECT;break;
	case 'E': pkt.evt.key_symbol=mtk_sym?DFB_BTN_EXIT:DIKS_ESCAPE;break;	
	case 'N': pkt.evt.key_symbol=mtk_sym?DFB_BTN_RETURN:DIKS_BACKSPACE;break;
	case 'i': pkt.evt.key_symbol=mtk_sym?DFB_BTN_PRG_INFO:DIKS_INFO;break;
	case 'M': pkt.evt.key_symbol=mtk_sym?DFB_BTN_MENU:DIKS_MENU;break;
	case 'L': pkt.evt.key_symbol=mtk_sym?DFB_BTN_CURSOR_LEFT:DIKS_CURSOR_LEFT;break;
	case 'R': pkt.evt.key_symbol=mtk_sym?DFB_BTN_CURSOR_RIGHT:DIKS_CURSOR_RIGHT;break;
	case 'U': pkt.evt.key_symbol=mtk_sym?DFB_BTN_CURSOR_UP:DIKS_CURSOR_UP;break;
	case 'D': pkt.evt.key_symbol=mtk_sym?DFB_BTN_CURSOR_DOWN:DIKS_CURSOR_DOWN;break;
	}

	//sending 2 event, press + release	
   	write ( sock, &pkt, sizeof(pkt) ); //press
	pkt.evt.type       = DIET_KEYRELEASE ;
   	write ( sock, &pkt, sizeof(pkt) ); //release
   }
   
leave:
   write ( sock, pkt, 0 );
   close (sock);
   exit(0);
 
}
