brintos

brintos / linux-shallow public Read only

0
0
Text · 9.0 KiB · 3d810bc Raw
374 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>4 *               2005-2007 Takahiro Hirofuchi5 * Copyright (C) 2015-2016 Samsung Electronics6 *               Igor Kotrasinski <i.kotrasinsk@samsung.com>7 *               Krzysztof Opasiak <k.opasiak@samsung.com>8 */9 10#include <sys/types.h>11#include <libudev.h>12 13#include <errno.h>14#include <stdbool.h>15#include <stdint.h>16#include <stdio.h>17#include <stdlib.h>18#include <string.h>19 20#include <getopt.h>21#include <netdb.h>22#include <unistd.h>23 24#include <dirent.h>25 26#include <linux/usb/ch9.h>27 28#include "usbip_common.h"29#include "usbip_network.h"30#include "usbip.h"31 32static const char usbip_list_usage_string[] =33	"usbip list [-p|--parsable] <args>\n"34	"    -p, --parsable         Parsable list format\n"35	"    -r, --remote=<host>    List the exportable USB devices on <host>\n"36	"    -l, --local            List the local USB devices\n"37	"    -d, --device           List the local USB gadgets bound to usbip-vudc\n";38 39void usbip_list_usage(void)40{41	printf("usage: %s", usbip_list_usage_string);42}43 44static int get_exported_devices(char *host, int sockfd)45{46	char product_name[100];47	char class_name[100];48	struct op_devlist_reply reply;49	uint16_t code = OP_REP_DEVLIST;50	struct usbip_usb_device udev;51	struct usbip_usb_interface uintf;52	unsigned int i;53	int rc, j;54	int status;55 56	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);57	if (rc < 0) {58		dbg("usbip_net_send_op_common failed");59		return -1;60	}61 62	rc = usbip_net_recv_op_common(sockfd, &code, &status);63	if (rc < 0) {64		err("Exported Device List Request failed - %s\n",65		    usbip_op_common_status_string(status));66		return -1;67	}68 69	memset(&reply, 0, sizeof(reply));70	rc = usbip_net_recv(sockfd, &reply, sizeof(reply));71	if (rc < 0) {72		dbg("usbip_net_recv_op_devlist failed");73		return -1;74	}75	PACK_OP_DEVLIST_REPLY(0, &reply);76	dbg("exportable devices: %d\n", reply.ndev);77 78	if (reply.ndev == 0) {79		info("no exportable devices found on %s", host);80		return 0;81	}82 83	printf("Exportable USB devices\n");84	printf("======================\n");85	printf(" - %s\n", host);86 87	for (i = 0; i < reply.ndev; i++) {88		memset(&udev, 0, sizeof(udev));89		rc = usbip_net_recv(sockfd, &udev, sizeof(udev));90		if (rc < 0) {91			dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);92			return -1;93		}94		usbip_net_pack_usb_device(0, &udev);95 96		usbip_names_get_product(product_name, sizeof(product_name),97					udev.idVendor, udev.idProduct);98		usbip_names_get_class(class_name, sizeof(class_name),99				      udev.bDeviceClass, udev.bDeviceSubClass,100				      udev.bDeviceProtocol);101		printf("%11s: %s\n", udev.busid, product_name);102		printf("%11s: %s\n", "", udev.path);103		printf("%11s: %s\n", "", class_name);104 105		for (j = 0; j < udev.bNumInterfaces; j++) {106			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));107			if (rc < 0) {108				err("usbip_net_recv failed: usbip_usb_intf[%d]",109						j);110 111				return -1;112			}113			usbip_net_pack_usb_interface(0, &uintf);114 115			usbip_names_get_class(class_name, sizeof(class_name),116					uintf.bInterfaceClass,117					uintf.bInterfaceSubClass,118					uintf.bInterfaceProtocol);119			printf("%11s: %2d - %s\n", "", j, class_name);120		}121 122		printf("\n");123	}124 125	return 0;126}127 128static int list_exported_devices(char *host)129{130	int rc;131	int sockfd;132 133	sockfd = usbip_net_tcp_connect(host, usbip_port_string);134	if (sockfd < 0) {135		err("could not connect to %s:%s: %s", host,136		    usbip_port_string, gai_strerror(sockfd));137		return -1;138	}139	dbg("connected to %s:%s", host, usbip_port_string);140 141	rc = get_exported_devices(host, sockfd);142	if (rc < 0) {143		err("failed to get device list from %s", host);144		return -1;145	}146 147	close(sockfd);148 149	return 0;150}151 152static void print_device(const char *busid, const char *vendor,153			 const char *product, bool parsable)154{155	if (parsable)156		printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);157	else158		printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);159}160 161static void print_product_name(char *product_name, bool parsable)162{163	if (!parsable)164		printf("   %s\n", product_name);165}166 167static int list_devices(bool parsable)168{169	struct udev *udev;170	struct udev_enumerate *enumerate;171	struct udev_list_entry *devices, *dev_list_entry;172	struct udev_device *dev;173	const char *path;174	const char *idVendor;175	const char *idProduct;176	const char *bConfValue;177	const char *bNumIntfs;178	const char *busid;179	char product_name[128];180	int ret = -1;181	const char *devpath;182 183	/* Create libudev context. */184	udev = udev_new();185 186	/* Create libudev device enumeration. */187	enumerate = udev_enumerate_new(udev);188 189	/* Take only USB devices that are not hubs and do not have190	 * the bInterfaceNumber attribute, i.e. are not interfaces.191	 */192	udev_enumerate_add_match_subsystem(enumerate, "usb");193	udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");194	udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);195	udev_enumerate_scan_devices(enumerate);196 197	devices = udev_enumerate_get_list_entry(enumerate);198 199	/* Show information about each device. */200	udev_list_entry_foreach(dev_list_entry, devices) {201		path = udev_list_entry_get_name(dev_list_entry);202		dev = udev_device_new_from_syspath(udev, path);203 204		/* Ignore devices attached to vhci_hcd */205		devpath = udev_device_get_devpath(dev);206		if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {207			dbg("Skip the device %s already attached to %s\n",208			    devpath, USBIP_VHCI_DRV_NAME);209			continue;210		}211 212		/* Get device information. */213		idVendor = udev_device_get_sysattr_value(dev, "idVendor");214		idProduct = udev_device_get_sysattr_value(dev, "idProduct");215		bConfValue = udev_device_get_sysattr_value(dev,216				"bConfigurationValue");217		bNumIntfs = udev_device_get_sysattr_value(dev,218				"bNumInterfaces");219		busid = udev_device_get_sysname(dev);220		if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {221			err("problem getting device attributes: %s",222			    strerror(errno));223			goto err_out;224		}225 226		/* Get product name. */227		usbip_names_get_product(product_name, sizeof(product_name),228					strtol(idVendor, NULL, 16),229					strtol(idProduct, NULL, 16));230 231		/* Print information. */232		print_device(busid, idVendor, idProduct, parsable);233		print_product_name(product_name, parsable);234 235		printf("\n");236 237		udev_device_unref(dev);238	}239 240	ret = 0;241 242err_out:243	udev_enumerate_unref(enumerate);244	udev_unref(udev);245 246	return ret;247}248 249static int list_gadget_devices(bool parsable)250{251	int ret = -1;252	struct udev *udev;253	struct udev_enumerate *enumerate;254	struct udev_list_entry *devices, *dev_list_entry;255	struct udev_device *dev;256	const char *path;257	const char *driver;258 259	const struct usb_device_descriptor *d_desc;260	const char *descriptors;261	char product_name[128];262 263	uint16_t idVendor;264	char idVendor_buf[8];265	uint16_t idProduct;266	char idProduct_buf[8];267	const char *busid;268 269	udev = udev_new();270	enumerate = udev_enumerate_new(udev);271 272	udev_enumerate_add_match_subsystem(enumerate, "platform");273 274	udev_enumerate_scan_devices(enumerate);275	devices = udev_enumerate_get_list_entry(enumerate);276 277	udev_list_entry_foreach(dev_list_entry, devices) {278		path = udev_list_entry_get_name(dev_list_entry);279		dev = udev_device_new_from_syspath(udev, path);280 281		driver = udev_device_get_driver(dev);282		/* We only have mechanism to enumerate gadgets bound to vudc */283		if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))284			continue;285 286		/* Get device information. */287		descriptors = udev_device_get_sysattr_value(dev,288				VUDC_DEVICE_DESCR_FILE);289 290		if (!descriptors) {291			err("problem getting device attributes: %s",292			    strerror(errno));293			goto err_out;294		}295 296		d_desc = (const struct usb_device_descriptor *) descriptors;297 298		idVendor = le16toh(d_desc->idVendor);299		sprintf(idVendor_buf, "0x%4x", idVendor);300		idProduct = le16toh(d_desc->idProduct);301		sprintf(idProduct_buf, "0x%4x", idVendor);302		busid = udev_device_get_sysname(dev);303 304		/* Get product name. */305		usbip_names_get_product(product_name, sizeof(product_name),306					le16toh(idVendor),307					le16toh(idProduct));308 309		/* Print information. */310		print_device(busid, idVendor_buf, idProduct_buf, parsable);311		print_product_name(product_name, parsable);312 313		printf("\n");314 315		udev_device_unref(dev);316	}317	ret = 0;318 319err_out:320	udev_enumerate_unref(enumerate);321	udev_unref(udev);322 323	return ret;324}325 326int usbip_list(int argc, char *argv[])327{328	static const struct option opts[] = {329		{ "parsable", no_argument,       NULL, 'p' },330		{ "remote",   required_argument, NULL, 'r' },331		{ "local",    no_argument,       NULL, 'l' },332		{ "device",    no_argument,       NULL, 'd' },333		{ NULL,       0,                 NULL,  0  }334	};335 336	bool parsable = false;337	int opt;338	int ret = -1;339 340	if (usbip_names_init(USBIDS_FILE))341		err("failed to open %s", USBIDS_FILE);342 343	for (;;) {344		opt = getopt_long(argc, argv, "pr:ld", opts, NULL);345 346		if (opt == -1)347			break;348 349		switch (opt) {350		case 'p':351			parsable = true;352			break;353		case 'r':354			ret = list_exported_devices(optarg);355			goto out;356		case 'l':357			ret = list_devices(parsable);358			goto out;359		case 'd':360			ret = list_gadget_devices(parsable);361			goto out;362		default:363			goto err_out;364		}365	}366 367err_out:368	usbip_list_usage();369out:370	usbip_names_free();371 372	return ret;373}374