// SerialPort.cpp
#include "SerialPort.h"
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <iostream>

SerialPort::SerialPort() : fd(-1) {}

SerialPort::~SerialPort()
{
    closePort();
}

speed_t SerialPort::getBaudrate(int baudrate)
{
    switch (baudrate)
    {
    case 115200:
        return B115200;
    case 57600:
        return B57600;
    case 38400:
        return B38400;
    case 19200:
        return B19200;
    case 9600:
        return B9600;
    case 4800:
        return B4800;
    case 2400:
        return B2400;
    default:
        return B115200;
    }
}

bool SerialPort::openPort(const std::string &portName, int baudrate)
{
    fd = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0)
    {
        std::cerr << "打开串口失败: " << strerror(errno) << std::endl;
        return false;
    }

    if (tcgetattr(fd, &tty) != 0)
    {
        std::cerr << "tcgetattr 失败: " << strerror(errno) << std::endl;
        close(fd);
        fd = -1;
        return false;
    }

    cfsetospeed(&tty, getBaudrate(baudrate));
    cfsetispeed(&tty, getBaudrate(baudrate));

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
    tty.c_cflag |= (CLOCAL | CREAD);
    tty.c_cflag &= ~(PARENB | PARODD);
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tty.c_oflag &= ~OPOST;

    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 0;

    if (tcsetattr(fd, TCSANOW, &tty) != 0)
    {
        std::cerr << "tcsetattr 失败: " << strerror(errno) << std::endl;
        close(fd);
        fd = -1;
        return false;
    }

    return true;
}

void SerialPort::closePort()
{
    if (fd >= 0)
    {
        close(fd);
        fd = -1;
    }
}

bool SerialPort::writeData(const uint8_t *data, size_t size)
{
    if (fd < 0)
    {
        std::cerr << "串口未打开" << std::endl;
        return false;
    }

    ssize_t written = write(fd, data, size);
    if (written < 0)
    {
        std::cerr << "写串口失败: " << strerror(errno) << std::endl;
        return false;
    }
    return written == (ssize_t)size;
}
