
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>

#include "SerialPort.h"

#include "android/log.h"

#ifdef DEPENDING_GPIO
#include "GPIOControl.h"
#endif

static const char *TAG = "serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

/*
static speed_t getBaudrate(int baudrate)
{
	switch(baudrate) {
		case 0: return B0;
		case 50: return B50;
		case 75: return B75;
		case 110: return B110;
		case 134: return B134;
		case 150: return B150;
		case 200: return B200;
		case 300: return B300;
		case 600: return B600;
		case 1200: return B1200;
		case 1800: return B1800;
		case 2400: return B2400;
		case 4800: return B4800;
		case 9600: return B9600;
		case 19200: return B19200;
		case 38400: return B38400;
		case 57600: return B57600;
		case 115200: return B115200;
		case 230400: return B230400;
		case 460800: return B460800;
		case 500000: return B500000;
		case 576000: return B576000;
		case 921600: return B921600;
		case 1000000: return B1000000;
		case 1152000: return B1152000;
		case 1500000: return B1500000;
		case 2000000: return B2000000;
		case 2500000: return B2500000;
		case 3000000: return B3000000;
		case 3500000: return B3500000;
		case 4000000: return B4000000;
		default: return -1;
	}
}
*/

bool CSerialPort::Open(const char* path, speed_t baudrate, int stopBits, int dataBits, int parity, int flowCon, int flags)
{
	if (baudrate == -1) {
		return false;
	}

	/* Opening device */
	{
		fd = open(path, O_RDWR | flags);
		if (fd == -1) {
			return false;
		}
	}

	/* Configure device */
	{
		struct termios cfg;
		if (tcgetattr(fd, &cfg))
		{
			close(fd);
			return false;
		}

		cfmakeraw(&cfg);
		cfsetispeed(&cfg, baudrate);
		cfsetospeed(&cfg, baudrate);

		cfg.c_cflag &= ~CSIZE;
		switch (dataBits) {
			case CS5:
			case CS6:
			case CS7:
			case CS8:
				cfg.c_cflag |= dataBits;    //使用8位数据位
				break;
			default:
				cfg.c_cflag |= CS8;
				break;
		}

		switch (parity) {
			case 0:
				cfg.c_cflag &= ~PARENB;    //无奇偶校验
				break;
			case 1:
				cfg.c_cflag |= (PARODD | PARENB);   //奇校验
				break;
			case 2:
				cfg.c_iflag &= ~(IGNPAR | PARMRK); // 偶校验
				cfg.c_iflag |= INPCK;
				cfg.c_cflag |= PARENB;
				cfg.c_cflag &= ~PARODD;
				break;
			default:
				cfg.c_cflag &= ~PARENB;
				break;
		}

		switch (stopBits) {
			case 1:
				cfg.c_cflag &= ~CSTOPB;    //1位停止位
				break;
			case 2:
				cfg.c_cflag |= CSTOPB;    //2位停止位
				break;
			default:
				break;
		}

		// hardware flow control
		switch (flowCon) {
			case 0:
				cfg.c_cflag &= ~CRTSCTS;    //不使用流控
				break;
			case 1:
				cfg.c_cflag |= CRTSCTS;    //硬件流控
				break;
			case 2:
				cfg.c_cflag |= IXON | IXOFF | IXANY;    //软件流控
				break;
			default:
				cfg.c_cflag &= ~CRTSCTS;
				break;
		}


		if (tcsetattr(fd, TCSANOW, &cfg)) {
			LOGE("tcsetattr() failed");
			close(fd);
			/* TODO: throw an exception */
			return false;
		}
	}

	return true;
}

void CSerialPort::Close()
{
	close(fd);
}