/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <termios.h>

#include "os/mynewt.h"
#include "native_uart_cfg_priv.h"

/* uint64 is used here to accommodate speed_t, whatever that is. */
static const uint64_t uart_baud_table[][2] = {
#ifdef B50 
    { 50, B50 },
#endif
#ifdef B75 
    { 75, B75 },
#endif
#ifdef B110 
    { 110, B110 },
#endif
#ifdef B134 
    { 134, B134 },
#endif
#ifdef B150 
    { 150, B150 },
#endif
#ifdef B200 
    { 200, B200 },
#endif
#ifdef B300 
    { 300, B300 },
#endif
#ifdef B600 
    { 600, B600 },
#endif
#ifdef B1200 
    { 1200, B1200 },
#endif
#ifdef B1800 
    { 1800, B1800 },
#endif
#ifdef B2400 
    { 2400, B2400 },
#endif
#ifdef B4800 
    { 4800, B4800 },
#endif
#ifdef B9600 
    { 9600, B9600 },
#endif
#ifdef B19200 
    { 19200, B19200 },
#endif
#ifdef B38400 
    { 38400, B38400 },
#endif
#ifdef B57600 
    { 57600, B57600 },
#endif
#ifdef B115200 
    { 115200, B115200 },
#endif
#ifdef B230400 
    { 230400, B230400 },
#endif
#ifdef B460800 
    { 460800, B460800 },
#endif
#ifdef B500000 
    { 500000, B500000 },
#endif
#ifdef B576000 
    { 576000, B576000 },
#endif
#ifdef B921600 
    { 921600, B921600 },
#endif
#ifdef B1000000 
    { 1000000, B1000000 },
#endif
#ifdef B1152000 
    { 1152000, B1152000 },
#endif
#ifdef B1500000 
    { 1500000, B1500000 },
#endif
#ifdef B2000000 
    { 2000000, B2000000 },
#endif
#ifdef B2500000
    { 2500000, B2500000 },
#endif
#ifdef B3000000
    { 3000000, B3000000 },
#endif
#ifdef B3500000
    { 3500000, B3500000 },
#endif
#ifdef B3710000
    { 3710000, B3710000 },
#endif
#ifdef B4000000
    { 4000000, B4000000 },
#endif
};
#define UART_BAUD_TABLE_SZ (sizeof uart_baud_table / sizeof uart_baud_table[0])

/**
 * Returns 0 on failure.
 */
speed_t
uart_baud_to_speed(int_least32_t baud)
{
    int i;

    for (i = 0; i < UART_BAUD_TABLE_SZ; i++) {
        if (uart_baud_table[i][0] == baud) {
            return uart_baud_table[i][1];
        }
    }

    return 0;
}

/**
 * Configures an external device terminal (/dev/cu.<...>).
 */
int
uart_dev_set_attr(int fd, int32_t baudrate, uint8_t databits,
                  uint8_t stopbits, enum hal_uart_parity parity,
                  enum hal_uart_flow_ctl flow_ctl)
{
    struct termios tty;
    speed_t speed;
    int rc;

    assert(fd >= 0);

    memset(&tty, 0, sizeof(tty));
    cfmakeraw(&tty);

    speed = uart_baud_to_speed(baudrate);
    if (speed == 0) {
        fprintf(stderr, "invalid baud rate: %d\n", (int)baudrate);
        assert(0);
    }

    tty.c_cflag |= (speed | CLOCAL | CREAD);

    /* Set flow control. */
    switch (flow_ctl) {
    case HAL_UART_FLOW_CTL_NONE:
        tty.c_cflag &= ~CRTSCTS;
        break;

    case HAL_UART_FLOW_CTL_RTS_CTS:
        tty.c_cflag |= CRTSCTS;
        break;

    default:
        fprintf(stderr, "invalid flow control setting: %d\n", flow_ctl);
        return -1;
    }

    errno = 0;
    rc = cfsetospeed(&tty, speed);
    if (rc != 0) {
        fprintf(stderr, "cfsetospeed failed; %d (%s) baudrate=%d\n",
                errno, strerror(errno), (int)baudrate);
        return -1;
    }

    errno = 0;
    rc = cfsetispeed(&tty, speed);
    if (rc != 0) {
        fprintf(stderr, "cfsetispeed failed; %d (%s) baudrate=%d\n",
                errno, strerror(errno), (int)baudrate);
        return -1;
    }

    switch (databits) {
    case 7:
        tty.c_cflag |= CS7;

        switch (parity) {
        case HAL_UART_PARITY_ODD:
            tty.c_cflag |= PARENB;
            tty.c_cflag |= PARODD;
            tty.c_cflag &= ~CSTOPB;
            tty.c_cflag &= ~CSIZE;
            break;

        case HAL_UART_PARITY_EVEN:
            tty.c_cflag |= PARENB;
            tty.c_cflag &= ~PARODD;
            tty.c_cflag &= ~CSTOPB;
            tty.c_cflag &= ~CSIZE;
            break;

        default:
            return SYS_EINVAL;
        }

    case 8:
        if (parity != HAL_UART_PARITY_NONE) {
            return SYS_EINVAL;
        }
        tty.c_cflag |= CS8;
        tty.c_cflag &= ~PARENB;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CSIZE;
        break;

    default:
        return SYS_EINVAL;
    }

    rc = tcsetattr(fd, TCSANOW, &tty);
    if (rc != 0) {
        fprintf(stderr, "tcsetattr failed; %d (%s)\n", errno, strerror(errno));
        return -1;
    }

    return 0;
}

