/* MaxLinear, Inc. retains all right, title and interest (including all intellectual
* property rights) in and to this computer program, which is protected by applicable
* intellectual property laws.  Unless you have obtained a separate written license from
* MaxLinear, Inc. or an authorized licensee of MaxLinear, Inc., you are not authorized
* to utilize all or a part of this computer program for any purpose (including
* reproduction, distribution, modification, and compilation into object code), and you
* must immediately destroy or return all copies of this computer program.  If you are
* licensed by MaxLinear, Inc. or an authorized licensee of MaxLinear, Inc., your rights
* to utilize this computer program are limited by the terms of that license.
*
* This computer program contains trade secrets owned by MaxLinear, Inc. and, unless
* authorized by MaxLinear, Inc. in writing, you agree to maintain the confidentiality
* of this computer program and related information and to not disclose this computer
* program and related information to any other person or entity.
*
* Misuse of this computer program or any information contained in it may results in
* violations of applicable law.  MaxLinear, Inc. vigorously enforces its copyright,
* trade secret, patent, contractual, and other legal rights.
*
* THIS COMPUTER PROGRAM IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, AND 
 *  MAXLINEAR, INC.
* EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING THE 
 * WARRANTIES OF
* MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
 * NONINFRINGEMENT.
*
****************************************************************************************
*                                        Copyright (c) 2010, MaxLinear, Inc.
****************************************************************************************/

// updated June 10, 2015

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <termio.h>
#include <time.h>
//#include <curses.h>

#include <errno.h>
#include "xr_usbserial_ioctl.h"

#include <strings.h>
#include <sys/time.h> 
#include <pthread.h>
#include <time.h>

struct xrioctl_rw_reg {
    int block;
	int reg;
	int regvalue;
};

typedef enum 
{
	RS232 = 0,
	RS485_HALF = 1,
	RS422_FULL = 2,
} UartRsmode_e;

int xrfd = -1;
int special_baud_rate = 0;

int set_rsmode(int fd,int block,int value)
{
	int tmp[2];
	int result;
	tmp[0] = block;
  tmp[1] = value;
//	printf("set_rsmode tmp[0]=%d tmp[1]=%d\n", tmp[0],tmp[1]);
  result = ioctl(fd, XR_USB_SERIAL_SET_RSMODE, tmp);
	if (result < 0)
	{
		printf("Cannot do XR_USB_SERIAL_SET_RSMODE ioctl (%d)\n", result);
	}
	return result;
}

#if 0 // Unused for now
static void m_setswf(int fd, int swf)
{
  struct termios tty;
  tcgetattr(fd, &tty);
  if (swf)
   tty.c_iflag |= IXON | IXOFF;
  else
   tty.c_iflag &= ~(IXON|IXOFF|IXANY);
  tcsetattr(fd, TCSANOW, &tty);
}

/* Set hardware flow control. */
static void m_sethwf(int fd, int on)
{
  struct termios tty;
  tcgetattr(fd, &tty);
  if (on)
    tty.c_cflag |= CRTSCTS;
  else
    tty.c_cflag &= ~CRTSCTS;
  tcsetattr(fd, TCSANOW, &tty);
}

static void m_setbaudrate(int fd, char *baudr)
{
  int spd = -1;
  int newbaud;
  struct termios tty;
  tcgetattr(fd, &tty);
  special_baud_rate = 0;
  /* Check if 'baudr' is really a number */
  if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')
    newbaud = -1;
  printf("m_setbaudrate = %d\n",newbaud); 
  switch (newbaud) {
    case 0:
#ifdef B0
      spd = B0;
#else
      spd = 0;
#endif
      break;
    case 3:	spd = B300;	break;
    case 6:	spd = B600;	break;
    case 12:	spd = B1200;	break;
    case 24:	spd = B2400;	break;
    case 48:	spd = B4800;	break;
    case 96:	spd = B9600;	break;
#ifdef B19200
    case 192:	spd = B19200;	break;
#else /* B19200 */
#  ifdef EXTA
    case 192:	spd = EXTA;	break;
#   else /* EXTA */
    case 192:	spd = B9600;	break;
#   endif /* EXTA */
#endif	 /* B19200 */
#ifdef B38400
    case 384:	spd = B38400;	break;
#else /* B38400 */
#  ifdef EXTB
    case 384:	spd = EXTB;	break;
#   else /* EXTB */
    case 384:	spd = B9600;	break;
#   endif /* EXTB */
#endif	 /* B38400 */
#ifdef B57600
    case 576:	spd = B57600;	break;
#endif
#ifdef B115200
    case 1152:	spd = B115200;	break;
#endif
#ifdef B230400
    case 2304:	spd = B230400;	break;
#endif
#ifdef B460800
    case 4608: spd = B460800; break;
#endif
#ifdef B500000
    case 5000: spd = B500000; break;
#endif
#ifdef B576000
    case 5760: spd = B576000; break;
#endif
#ifdef B921600
    case 9216: spd = B921600; break;
#endif
#ifdef B1000000
    case 10000: spd = B1000000; break;
#endif
#ifdef B1152000
    case 11520: spd = B1152000; break;
#endif
#ifdef B1500000
    case 15000: spd = B1500000; break;
#endif
#ifdef B2000000
    case 20000: spd = B2000000; break;
#endif
#ifdef B2500000
    case 25000: spd = B2500000; break;
#endif
#ifdef B3000000
    case 30000: spd = B3000000; break;
#endif
#ifdef B3500000
    case 35000: spd = B3500000; break;
#endif
#ifdef B4000000
    case 40000: spd = B4000000; break;
#endif
  }

  if (spd != -1) {
    cfsetospeed(&tty, (speed_t)spd);
    cfsetispeed(&tty, (speed_t)spd);
  }
  else
  {
     special_baud_rate = atol(baudr); 
  }
 
  /* Set into raw, no echo mode */
  tty.c_iflag =  IGNBRK;
  tty.c_lflag = 0;
  tty.c_oflag = 0;
  tty.c_cflag |= CLOCAL | CREAD;
  tty.c_cc[VMIN] = 1;
  tty.c_cc[VTIME] = 5;
  tcsetattr(fd, TCSANOW, &tty);


}

static void m_set_parity(int fd, char *parity)
{
  struct termios tty;
  tcgetattr(fd, &tty);
  tty.c_cflag &= ~(PARENB | PARODD);
  if (parity[0] == 'E')
    tty.c_cflag |= PARENB;
  else if (parity[0] == 'O')
    tty.c_cflag |= (PARENB | PARODD);
  tcsetattr(fd, TCSANOW, &tty);

}
static void m_set_bit(int fd, char *bits)
{
  int bit = bits[0];
  struct termios tty;
  tcgetattr(fd, &tty);
 
  switch (bit)
  {
    case '5':
      tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
      break;
    case '7':
      tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
      break;
    case '8':
    default:
      tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
      break;
  }
  /* Set into raw, no echo mode */
  tty.c_iflag =  IGNBRK;
  tty.c_lflag = 0;
  tty.c_oflag = 0;
  tty.c_cflag |= CLOCAL | CREAD;
  tty.c_cc[VMIN] = 1;
  tty.c_cc[VTIME] = 5;
  tcsetattr(fd, TCSANOW, &tty);
}

static void m_set_stopbit(int fd,char *stopb)
{
  struct termios tty;
  tcgetattr(fd, &tty);
 
  /* Set into raw, no echo mode */
  tty.c_iflag =  IGNBRK;
  tty.c_lflag = 0;
  tty.c_oflag = 0;
  tty.c_cflag |= CLOCAL | CREAD;
  tty.c_cc[VMIN] = 1;
  tty.c_cc[VTIME] = 5;
  
  if (stopb[0] == '2')
    tty.c_cflag |= CSTOPB;
  else
    tty.c_cflag &= ~CSTOPB;
  tcsetattr(fd, TCSANOW, &tty);

}
#endif

void usage(void)
{
  printf("Usage: ./utek_gpio_mode_select_util <device> <mode>	\n");
  printf("mode:RS232, RS485, RS422\n");
  printf("        RS232 : RS-232 mode\n");
  printf("        RS485 : RS-485 Half Duplex mode\n");
  printf("        RS422 : RS-422 Full Duplex mode\n");
  printf("For example:\n");
  printf("           ./utek_gpio_mode_select_util /dev/ttyXRUSB0 RS485\n");
  exit(1);
}

int main(int argc, char **argv)
{
char * device = NULL;
int result;
int rs_mode = 0;

if(argc != 3)
{
  usage();
}

device = argv[1];

printf("Exar/MxL Serial Device:%s \n", device);

if(strncmp(argv[2],"RS232",5) == 0)
{
	rs_mode = RS232;
}
else if(strncmp(argv[2],"RS485",5) == 0)
{
	rs_mode = RS485_HALF;
}
else if(strncmp(argv[2],"RS422",5) == 0)
{
	rs_mode = RS422_FULL;
}
else
{
	printf("Mode entered is invalid! please check!\n");   
	usage();
}

// Only open COM port if all parameter is good
/*O_RDWR | O_NOCTTY | O_NONBLOCK*/
xrfd = open(device, O_RDWR | O_NOCTTY);

if(xrfd <= 0) 
{
	printf("Can't open device %s ret=%d\n", device,xrfd);
	return 1;
}
else
{
	result = set_rsmode(xrfd,-1,rs_mode);	
	if(result < 0)
	{
	  printf("Set_rsmodes Failed:%d\n",result);
	}
	
	close(xrfd);
	return 0;
}

}

