File Index
Files and directories
Sign in
FILE

usbip_list.c

File preview with syntax highlighting.

linux-6.19.14/tools/usb/usbip/src/usbip_list.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
  4 *               2005-2007 Takahiro Hirofuchi
  5 * Copyright (C) 2015-2016 Samsung Electronics
  6 *               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	else
158		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 have
190	 * 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}
~/ Read-only file preview.