/*
 * ionapp_export.c
 *
 * It is a user space utility to create and export android
 * ion memory buffer fd to another process using unix domain socket as IPC.
 * This acts like a server for ionapp_import(client).
 * So, this server has to be started first before the client.
 *
 * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include "ionutils.h"
#include "ipcsocket.h"


void print_usage(int argc, char *argv[])
{
	printf("Usage: %s [-h <help>] [-i <heap id>] [-s <size in bytes>]\n",
		argv[0]);
}

int main(int argc, char *argv[])
{
	int opt, ret, status, heapid;
	int sockfd, client_fd, shared_fd;
	unsigned char *map_buf;
	unsigned long map_len, heap_type, heap_size, flags;
	struct ion_buffer_info info;
	struct socket_info skinfo;

	if (argc < 2) {
		print_usage(argc, argv);
		return -1;
	}

	heap_size = 0;
	flags = 0;
	heap_type = ION_HEAP_TYPE_SYSTEM;

	while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
		switch (opt) {
		case 'h':
			print_usage(argc, argv);
			exit(0);
			break;
		case 'i':
			heapid = atoi(optarg);
			switch (heapid) {
			case 0:
				heap_type = ION_HEAP_TYPE_SYSTEM;
				break;
			case 1:
				heap_type = ION_HEAP_TYPE_SYSTEM_CONTIG;
				break;
			default:
				printf("ERROR: heap type not supported\n");
				exit(1);
			}
			break;
		case 's':
			heap_size = atoi(optarg);
			break;
		default:
			print_usage(argc, argv);
			exit(1);
			break;
		}
	}

	if (heap_size <= 0) {
		printf("heap_size cannot be 0\n");
		print_usage(argc, argv);
		exit(1);
	}

	printf("heap_type: %ld, heap_size: %ld\n", heap_type, heap_size);
	info.heap_type = heap_type;
	info.heap_size = heap_size;
	info.flag_type = flags;

	/* This is server: open the socket connection first */
	/* Here; 1 indicates server or exporter */
	status = opensocket(&sockfd, SOCKET_NAME, 1);
	if (status < 0) {
		fprintf(stderr, "<%s>: Failed opensocket.\n", __func__);
		goto err_socket;
	}
	skinfo.sockfd = sockfd;

	ret = ion_export_buffer_fd(&info);
	if (ret < 0) {
		fprintf(stderr, "FAILED: ion_get_buffer_fd\n");
		goto err_export;
	}
	client_fd = info.ionfd;
	shared_fd = info.buffd;
	map_buf = info.buffer;
	map_len = info.buflen;
	write_buffer(map_buf, map_len);

	/* share ion buf fd with other user process */
	printf("Sharing fd: %d, Client fd: %d\n", shared_fd, client_fd);
	skinfo.datafd = shared_fd;
	skinfo.buflen = map_len;

	ret = socket_send_fd(&skinfo);
	if (ret < 0) {
		fprintf(stderr, "FAILED: socket_send_fd\n");
		goto err_send;
	}

err_send:
err_export:
	ion_close_buffer_fd(&info);

err_socket:
	closesocket(sockfd, SOCKET_NAME);

	return 0;
}
