/*
 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
 *               2005-2007 Takahiro Hirofuchi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <sys/types.h>
#include <sysfs/libsysfs.h>

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

#include <getopt.h>
#include <netdb.h>
#include <unistd.h>

#include "usbip_common.h"
#include "usbip_network.h"
#include "usbip.h"

static const char usbip_list_usage_string[] =
	"usbip list [-p|--parsable] <args>\n"
	"    -p, --parsable         Parsable list format\n"
	"    -r, --remote=<host>    List the exportable USB devices on <host>\n"
	"    -l, --local            List the local USB devices\n";

void usbip_list_usage(void)
{
	printf("usage: %s", usbip_list_usage_string);
}

static int get_exported_devices(char *host, int sockfd)
{
	char product_name[100];
	char class_name[100];
	struct op_devlist_reply reply;
	uint16_t code = OP_REP_DEVLIST;
	struct usbip_usb_device udev;
	struct usbip_usb_interface uintf;
	unsigned int i;
	int j, rc;

	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
	if (rc < 0) {
		dbg("usbip_net_send_op_common failed");
		return -1;
	}

	rc = usbip_net_recv_op_common(sockfd, &code);
	if (rc < 0) {
		dbg("usbip_net_recv_op_common failed");
		return -1;
	}

	memset(&reply, 0, sizeof(reply));
	rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
	if (rc < 0) {
		dbg("usbip_net_recv_op_devlist failed");
		return -1;
	}
	PACK_OP_DEVLIST_REPLY(0, &reply);
	dbg("exportable devices: %d\n", reply.ndev);

	if (reply.ndev == 0) {
		info("no exportable devices found on %s", host);
		return 0;
	}

	printf("Exportable USB devices\n");
	printf("======================\n");
	printf(" - %s\n", host);

	for (i = 0; i < reply.ndev; i++) {
		memset(&udev, 0, sizeof(udev));
		rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
		if (rc < 0) {
			dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
			return -1;
		}
		usbip_net_pack_usb_device(0, &udev);

		usbip_names_get_product(product_name, sizeof(product_name),
					udev.idVendor, udev.idProduct);
		usbip_names_get_class(class_name, sizeof(class_name),
				      udev.bDeviceClass, udev.bDeviceSubClass,
				      udev.bDeviceProtocol);
		printf("%11s: %s\n", udev.busid, product_name);
		printf("%11s: %s\n", "", udev.path);
		printf("%11s: %s\n", "", class_name);

		for (j = 0; j < udev.bNumInterfaces; j++) {
			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
			if (rc < 0) {
				dbg("usbip_net_recv failed: usbip_usb_intf[%d]",
				    j);

				return -1;
			}
			usbip_net_pack_usb_interface(0, &uintf);

			usbip_names_get_class(class_name, sizeof(class_name),
					      uintf.bInterfaceClass,
					      uintf.bInterfaceSubClass,
					      uintf.bInterfaceProtocol);
			printf("%11s: %2d - %s\n", "", j, class_name);
		}
		printf("\n");
	}

	return 0;
}

static int list_exported_devices(char *host)
{
	int rc;
	int sockfd;

	sockfd = usbip_net_tcp_connect(host, USBIP_PORT_STRING);
	if (sockfd < 0) {
		err("could not connect to %s:%s: %s", host,
		    USBIP_PORT_STRING, gai_strerror(sockfd));
		return -1;
	}
	dbg("connected to %s:%s", host, USBIP_PORT_STRING);

	rc = get_exported_devices(host, sockfd);
	if (rc < 0) {
		err("failed to get device list from %s", host);
		return -1;
	}

	close(sockfd);

	return 0;
}

static void print_device(char *busid, char *vendor, char *product,
			 bool parsable)
{
	if (parsable)
		printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
	else
		printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
}

static void print_product_name(char *product_name, bool parsable)
{
	if (!parsable)
		printf("   %s\n", product_name);
}

static void print_interface(char *busid, char *driver, bool parsable)
{
	if (parsable)
		printf("%s=%s#", busid, driver);
	else
		printf("%9s%s -> %s\n", "", busid, driver);
}

static int is_device(void *x)
{
	struct sysfs_attribute *devpath;
	struct sysfs_device *dev = x;
	int ret = 0;

	devpath = sysfs_get_device_attr(dev, "devpath");
	if (devpath && *devpath->value != '0')
		ret = 1;

	return ret;
}

static int devcmp(void *a, void *b)
{
	return strcmp(a, b);
}

static int list_devices(bool parsable)
{
	char bus_type[] = "usb";
	char busid[SYSFS_BUS_ID_SIZE];
	char product_name[128];
	struct sysfs_bus *ubus;
	struct sysfs_device *dev;
	struct sysfs_device *intf;
	struct sysfs_attribute *idVendor;
	struct sysfs_attribute *idProduct;
	struct sysfs_attribute *bConfValue;
	struct sysfs_attribute *bNumIntfs;
	struct dlist *devlist;
	int i;
	int ret = -1;

	ubus = sysfs_open_bus(bus_type);
	if (!ubus) {
		err("could not open %s bus: %s", bus_type, strerror(errno));
		return -1;
	}

	devlist = sysfs_get_bus_devices(ubus);
	if (!devlist) {
		err("could not get %s bus devices: %s", bus_type,
		    strerror(errno));
		goto err_out;
	}

	/* remove interfaces and root hubs from device list */
	dlist_filter_sort(devlist, is_device, devcmp);

	if (!parsable) {
		printf("Local USB devices\n");
		printf("=================\n");
	}
	dlist_for_each_data(devlist, dev, struct sysfs_device) {
		idVendor   = sysfs_get_device_attr(dev, "idVendor");
		idProduct  = sysfs_get_device_attr(dev, "idProduct");
		bConfValue = sysfs_get_device_attr(dev, "bConfigurationValue");
		bNumIntfs  = sysfs_get_device_attr(dev, "bNumInterfaces");
		if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
			err("problem getting device attributes: %s",
			    strerror(errno));
			goto err_out;
		}

		/* get product name */
		usbip_names_get_product(product_name, sizeof(product_name),
					strtol(idVendor->value, NULL, 16),
					strtol(idProduct->value, NULL, 16));
		print_device(dev->bus_id, idVendor->value, idProduct->value,
			     parsable);
		print_product_name(product_name, parsable);

		for (i = 0; i < atoi(bNumIntfs->value); i++) {
			snprintf(busid, sizeof(busid), "%s:%.1s.%d",
				 dev->bus_id, bConfValue->value, i);
			intf = sysfs_open_device(bus_type, busid);
			if (!intf) {
				err("could not open device interface: %s",
				    strerror(errno));
				goto err_out;
			}
			print_interface(busid, intf->driver_name, parsable);
			sysfs_close_device(intf);
		}
		printf("\n");
	}

	ret = 0;

err_out:
	sysfs_close_bus(ubus);

	return ret;
}

int usbip_list(int argc, char *argv[])
{
	static const struct option opts[] = {
		{ "parsable", no_argument,       NULL, 'p' },
		{ "remote",   required_argument, NULL, 'r' },
		{ "local",    no_argument,       NULL, 'l' },
		{ NULL,       0,                 NULL,  0  }
	};

	bool parsable = false;
	int opt;
	int ret = -1;

	if (usbip_names_init(USBIDS_FILE))
		err("failed to open %s", USBIDS_FILE);

	for (;;) {
		opt = getopt_long(argc, argv, "pr:l", opts, NULL);

		if (opt == -1)
			break;

		switch (opt) {
		case 'p':
			parsable = true;
			break;
		case 'r':
			ret = list_exported_devices(optarg);
			goto out;
		case 'l':
			ret = list_devices(parsable);
			goto out;
		default:
			goto err_out;
		}
	}

err_out:
	usbip_list_usage();
out:
	usbip_names_free();

	return ret;
}
