// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2005-2007 Takahiro Hirofuchi
 */

#include <libudev.h>
#include "usbip_common.h"
#include "names.h"

#undef  PROGNAME
#define PROGNAME "libusbip"

int usbip_use_syslog;
int usbip_use_stderr;
int usbip_use_debug;

extern struct udev *udev_context;

struct speed_string {
	int num;
	char *speed;
	char *desc;
};

static const struct speed_string speed_strings[] = {
	{ USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
	{ USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
	{ USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
	{ USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
	{ USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
	{ USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
	{ USB_SPEED_SUPER_PLUS, "10000", "Super Speed Plus(10000Mbps)" },
	{ USB_SPEED_SUPER_PLUS, "20000", "Super Speed Plus(20000Mbps)" },
	{ 0, NULL, NULL }
};

struct portst_string {
	int num;
	char *desc;
};

static struct portst_string portst_strings[] = {
	{ SDEV_ST_AVAILABLE,	"Device Available" },
	{ SDEV_ST_USED,		"Device in Use" },
	{ SDEV_ST_ERROR,	"Device Error"},
	{ VDEV_ST_NULL,		"Port Available"},
	{ VDEV_ST_NOTASSIGNED,	"Port Initializing"},
	{ VDEV_ST_USED,		"Port in Use"},
	{ VDEV_ST_ERROR,	"Port Error"},
	{ 0, NULL}
};

const char *usbip_status_string(int32_t status)
{
	for (int i = 0; portst_strings[i].desc != NULL; i++)
		if (portst_strings[i].num == status)
			return portst_strings[i].desc;

	return "Unknown Status";
}

const char *usbip_speed_string(int num)
{
	for (int i = 0; speed_strings[i].speed != NULL; i++)
		if (speed_strings[i].num == num)
			return speed_strings[i].desc;

	return "Unknown Speed";
}

struct op_common_status_string {
	int num;
	char *desc;
};

static struct op_common_status_string op_common_status_strings[] = {
	{ ST_OK,	"Request Completed Successfully" },
	{ ST_NA,	"Request Failed" },
	{ ST_DEV_BUSY,	"Device busy (exported)" },
	{ ST_DEV_ERR,	"Device in error state" },
	{ ST_NODEV,	"Device not found" },
	{ ST_ERROR,	"Unexpected response" },
	{ 0, NULL}
};

const char *usbip_op_common_status_string(int status)
{
	for (int i = 0; op_common_status_strings[i].desc != NULL; i++)
		if (op_common_status_strings[i].num == status)
			return op_common_status_strings[i].desc;

	return "Unknown Op Common Status";
}

#define DBG_UDEV_INTEGER(name)\
	dbg("%-20s = %x", to_string(name), (int) udev->name)

#define DBG_UINF_INTEGER(name)\
	dbg("%-20s = %x", to_string(name), (int) uinf->name)

void dump_usb_interface(struct usbip_usb_interface *uinf)
{
	char buff[100];

	usbip_names_get_class(buff, sizeof(buff),
			uinf->bInterfaceClass,
			uinf->bInterfaceSubClass,
			uinf->bInterfaceProtocol);
	dbg("%-20s = %s", "Interface(C/SC/P)", buff);
}

void dump_usb_device(struct usbip_usb_device *udev)
{
	char buff[100];

	dbg("%-20s = %s", "path",  udev->path);
	dbg("%-20s = %s", "busid", udev->busid);

	usbip_names_get_class(buff, sizeof(buff),
			udev->bDeviceClass,
			udev->bDeviceSubClass,
			udev->bDeviceProtocol);
	dbg("%-20s = %s", "Device(C/SC/P)", buff);

	DBG_UDEV_INTEGER(bcdDevice);

	usbip_names_get_product(buff, sizeof(buff),
			udev->idVendor,
			udev->idProduct);
	dbg("%-20s = %s", "Vendor/Product", buff);

	DBG_UDEV_INTEGER(bNumConfigurations);
	DBG_UDEV_INTEGER(bNumInterfaces);

	dbg("%-20s = %s", "speed",
			usbip_speed_string(udev->speed));

	DBG_UDEV_INTEGER(busnum);
	DBG_UDEV_INTEGER(devnum);
}


int read_attr_value(struct udev_device *dev, const char *name,
		    const char *format)
{
	const char *attr;
	int num = 0;
	int ret;

	attr = udev_device_get_sysattr_value(dev, name);
	if (!attr) {
		err("udev_device_get_sysattr_value failed");
		goto err;
	}

	/* The client chooses the device configuration
	 * when attaching it so right after being bound
	 * to usbip-host on the server the device will
	 * have no configuration.
	 * Therefore, attributes such as bConfigurationValue
	 * and bNumInterfaces will not exist and sscanf will
	 * fail. Check for these cases and don't treat them
	 * as errors.
	 */

	ret = sscanf(attr, format, &num);
	if (ret < 1) {
		if (strcmp(name, "bConfigurationValue") &&
				strcmp(name, "bNumInterfaces")) {
			err("sscanf failed for attribute %s", name);
			goto err;
		}
	}

err:

	return num;
}


int read_attr_speed(struct udev_device *dev)
{
	const char *speed;

	speed = udev_device_get_sysattr_value(dev, "speed");
	if (!speed) {
		err("udev_device_get_sysattr_value failed");
		goto err;
	}

	for (int i = 0; speed_strings[i].speed != NULL; i++) {
		if (!strcmp(speed, speed_strings[i].speed))
			return speed_strings[i].num;
	}

err:

	return USB_SPEED_UNKNOWN;
}

#define READ_ATTR(object, type, dev, name, format)			      \
	do {								      \
		(object)->name = (type) read_attr_value(dev, to_string(name), \
							format);	      \
	} while (0)


int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
{
	uint32_t busnum, devnum;
	const char *path, *name;

	READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,		"%02x\n");
	READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,	"%02x\n");
	READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,	"%02x\n");

	READ_ATTR(udev, uint16_t, sdev, idVendor,		"%04x\n");
	READ_ATTR(udev, uint16_t, sdev, idProduct,		"%04x\n");
	READ_ATTR(udev, uint16_t, sdev, bcdDevice,		"%04x\n");

	READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,	"%02x\n");
	READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,	"%02x\n");
	READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,		"%02x\n");

	READ_ATTR(udev, uint8_t,  sdev, devnum,			"%d\n");
	udev->speed = read_attr_speed(sdev);

	path = udev_device_get_syspath(sdev);
	name = udev_device_get_sysname(sdev);

	strncpy(udev->path,  path,  SYSFS_PATH_MAX - 1);
	udev->path[SYSFS_PATH_MAX - 1] = '\0';
	strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE - 1);
	udev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0';

	sscanf(name, "%u-%u", &busnum, &devnum);
	udev->busnum = busnum;

	return 0;
}

int read_usb_interface(struct usbip_usb_device *udev, int i,
		       struct usbip_usb_interface *uinf)
{
	char busid[SYSFS_BUS_ID_SIZE];
	int size;
	struct udev_device *sif;

	size = snprintf(busid, sizeof(busid), "%s:%d.%d",
			udev->busid, udev->bConfigurationValue, i);
	if (size < 0 || (unsigned int)size >= sizeof(busid)) {
		err("busid length %i >= %lu or < 0", size,
		    (long unsigned)sizeof(busid));
		return -1;
	}

	sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
	if (!sif) {
		err("udev_device_new_from_subsystem_sysname %s failed", busid);
		return -1;
	}

	READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,		"%02x\n");
	READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,	"%02x\n");
	READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,	"%02x\n");

	return 0;
}

int usbip_names_init(char *f)
{
	return names_init(f);
}

void usbip_names_free(void)
{
	names_free();
}

void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
			     uint16_t product)
{
	const char *prod, *vend;

	prod = names_product(vendor, product);
	if (!prod)
		prod = "unknown product";


	vend = names_vendor(vendor);
	if (!vend)
		vend = "unknown vendor";

	snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
}

void usbip_names_get_class(char *buff, size_t size, uint8_t class,
			   uint8_t subclass, uint8_t protocol)
{
	const char *c, *s, *p;

	if (class == 0 && subclass == 0 && protocol == 0) {
		snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
		return;
	}

	p = names_protocol(class, subclass, protocol);
	if (!p)
		p = "unknown protocol";

	s = names_subclass(class, subclass);
	if (!s)
		s = "unknown subclass";

	c = names_class(class);
	if (!c)
		c = "unknown class";

	snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
}
