320 lines · 7.6 KB · C
RawDownload
// 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);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t