/*
 * Copyright (c) 2019 Intel Corporation
 * Copyright (c) 2022 Martin Jäger <martin@libre.solar>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 *
 * Routines setting up the host system. Those are placed in separate file
 * because there is naming conflicts between host and zephyr network stacks.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>

/* Linux host include files. */
#ifdef __linux
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#else
#error "This driver can only be built on Linux systems"
#endif

#include "can_native_linux_adapt.h"

#ifndef CANFD_FDF
/* Linux kernels before v5.14 do not define CANFD_FDF */
#define CANFD_FDF 0x04
#endif /* CANFD_FDF */

int linux_socketcan_iface_open(const char *if_name)
{
	struct sockaddr_can addr;
	struct ifreq ifr;
	int fd, opt, ret = -EINVAL;

	fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
	if (fd < 0) {
		return -errno;
	}

	(void)memset(&ifr, 0, sizeof(ifr));
	(void)memset(&addr, 0, sizeof(addr));

	strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);

	ret = ioctl(fd, SIOCGIFINDEX, (void *)&ifr);
	if (ret < 0) {
		close(fd);
		return -errno;
	}

	addr.can_ifindex = ifr.ifr_ifindex;
	addr.can_family = PF_CAN;

	ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
	if (ret < 0) {
		close(fd);
		return -errno;
	}

	/* this option must always be enabled in order to receive TX confirmations */
	opt = 1;
	ret = setsockopt(fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &opt, sizeof(opt));
	if (ret < 0) {
		close(fd);
		return -errno;
	}

	return fd;
}

int linux_socketcan_iface_close(int fd)
{
	return close(fd);
}

int linux_socketcan_poll_data(int fd)
{
	struct timeval timeout;
	fd_set rset;
	int ret;

	FD_ZERO(&rset);

	FD_SET(fd, &rset);

	timeout.tv_sec = 0;
	timeout.tv_usec = 0;

	ret = select(fd + 1, &rset, NULL, NULL, &timeout);
	if (ret < 0 && errno != EINTR) {
		return -errno;
	} else if (ret > 0) {
		if (FD_ISSET(fd, &rset)) {
			return 0;
		}
	}

	return -EAGAIN;
}

int linux_socketcan_read_data(int fd, void *buf, size_t buf_len, bool *msg_confirm)
{
	struct canfd_frame *frame = (struct canfd_frame *)buf;
	struct msghdr msg = {0};

	struct iovec iov = {
		.iov_base = buf,
		.iov_len = buf_len,
	};
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	int ret = (int)recvmsg(fd, &msg, MSG_WAITALL);

	if (msg_confirm != NULL) {
		*msg_confirm = (msg.msg_flags & MSG_CONFIRM) != 0;
	}

	/* Make sure to set the flags for all frames received via the Linux API.
	 *
	 * Zephyr relies on defined flags field of the SocketCAN data for both FD and classical CAN
	 * frames. In Linux the flags field is undefined for legacy frames.
	 */
	if (ret == CANFD_MTU) {
		frame->flags |= CANFD_FDF;
	} else if (ret == CAN_MTU) {
		frame->flags = 0;
	}

	return ret;
}

int linux_socketcan_set_mode_fd(int fd, bool mode_fd)
{
	int opt = mode_fd ? 1 : 0;

	return setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &opt, sizeof(opt));
}
