xref: /openbmc/linux/tools/usb/usbip/src/usbip_list.c (revision 588b48ca)
1588b48caSValentina Manea /*
2588b48caSValentina Manea  * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3588b48caSValentina Manea  *               2005-2007 Takahiro Hirofuchi
4588b48caSValentina Manea  *
5588b48caSValentina Manea  * This program is free software: you can redistribute it and/or modify
6588b48caSValentina Manea  * it under the terms of the GNU General Public License as published by
7588b48caSValentina Manea  * the Free Software Foundation, either version 2 of the License, or
8588b48caSValentina Manea  * (at your option) any later version.
9588b48caSValentina Manea  *
10588b48caSValentina Manea  * This program is distributed in the hope that it will be useful,
11588b48caSValentina Manea  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12588b48caSValentina Manea  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13588b48caSValentina Manea  * GNU General Public License for more details.
14588b48caSValentina Manea  *
15588b48caSValentina Manea  * You should have received a copy of the GNU General Public License
16588b48caSValentina Manea  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17588b48caSValentina Manea  */
18588b48caSValentina Manea 
19588b48caSValentina Manea #include <sys/types.h>
20588b48caSValentina Manea #include <libudev.h>
21588b48caSValentina Manea 
22588b48caSValentina Manea #include <errno.h>
23588b48caSValentina Manea #include <stdbool.h>
24588b48caSValentina Manea #include <stdint.h>
25588b48caSValentina Manea #include <stdio.h>
26588b48caSValentina Manea #include <stdlib.h>
27588b48caSValentina Manea #include <string.h>
28588b48caSValentina Manea 
29588b48caSValentina Manea #include <getopt.h>
30588b48caSValentina Manea #include <netdb.h>
31588b48caSValentina Manea #include <unistd.h>
32588b48caSValentina Manea 
33588b48caSValentina Manea #include "usbip_common.h"
34588b48caSValentina Manea #include "usbip_network.h"
35588b48caSValentina Manea #include "usbip.h"
36588b48caSValentina Manea 
37588b48caSValentina Manea static const char usbip_list_usage_string[] =
38588b48caSValentina Manea 	"usbip list [-p|--parsable] <args>\n"
39588b48caSValentina Manea 	"    -p, --parsable         Parsable list format\n"
40588b48caSValentina Manea 	"    -r, --remote=<host>    List the exportable USB devices on <host>\n"
41588b48caSValentina Manea 	"    -l, --local            List the local USB devices\n";
42588b48caSValentina Manea 
43588b48caSValentina Manea void usbip_list_usage(void)
44588b48caSValentina Manea {
45588b48caSValentina Manea 	printf("usage: %s", usbip_list_usage_string);
46588b48caSValentina Manea }
47588b48caSValentina Manea 
48588b48caSValentina Manea static int get_exported_devices(char *host, int sockfd)
49588b48caSValentina Manea {
50588b48caSValentina Manea 	char product_name[100];
51588b48caSValentina Manea 	char class_name[100];
52588b48caSValentina Manea 	struct op_devlist_reply reply;
53588b48caSValentina Manea 	uint16_t code = OP_REP_DEVLIST;
54588b48caSValentina Manea 	struct usbip_usb_device udev;
55588b48caSValentina Manea 	struct usbip_usb_interface uintf;
56588b48caSValentina Manea 	unsigned int i;
57588b48caSValentina Manea 	int rc, j;
58588b48caSValentina Manea 
59588b48caSValentina Manea 	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
60588b48caSValentina Manea 	if (rc < 0) {
61588b48caSValentina Manea 		dbg("usbip_net_send_op_common failed");
62588b48caSValentina Manea 		return -1;
63588b48caSValentina Manea 	}
64588b48caSValentina Manea 
65588b48caSValentina Manea 	rc = usbip_net_recv_op_common(sockfd, &code);
66588b48caSValentina Manea 	if (rc < 0) {
67588b48caSValentina Manea 		dbg("usbip_net_recv_op_common failed");
68588b48caSValentina Manea 		return -1;
69588b48caSValentina Manea 	}
70588b48caSValentina Manea 
71588b48caSValentina Manea 	memset(&reply, 0, sizeof(reply));
72588b48caSValentina Manea 	rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
73588b48caSValentina Manea 	if (rc < 0) {
74588b48caSValentina Manea 		dbg("usbip_net_recv_op_devlist failed");
75588b48caSValentina Manea 		return -1;
76588b48caSValentina Manea 	}
77588b48caSValentina Manea 	PACK_OP_DEVLIST_REPLY(0, &reply);
78588b48caSValentina Manea 	dbg("exportable devices: %d\n", reply.ndev);
79588b48caSValentina Manea 
80588b48caSValentina Manea 	if (reply.ndev == 0) {
81588b48caSValentina Manea 		info("no exportable devices found on %s", host);
82588b48caSValentina Manea 		return 0;
83588b48caSValentina Manea 	}
84588b48caSValentina Manea 
85588b48caSValentina Manea 	printf("Exportable USB devices\n");
86588b48caSValentina Manea 	printf("======================\n");
87588b48caSValentina Manea 	printf(" - %s\n", host);
88588b48caSValentina Manea 
89588b48caSValentina Manea 	for (i = 0; i < reply.ndev; i++) {
90588b48caSValentina Manea 		memset(&udev, 0, sizeof(udev));
91588b48caSValentina Manea 		rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
92588b48caSValentina Manea 		if (rc < 0) {
93588b48caSValentina Manea 			dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
94588b48caSValentina Manea 			return -1;
95588b48caSValentina Manea 		}
96588b48caSValentina Manea 		usbip_net_pack_usb_device(0, &udev);
97588b48caSValentina Manea 
98588b48caSValentina Manea 		usbip_names_get_product(product_name, sizeof(product_name),
99588b48caSValentina Manea 					udev.idVendor, udev.idProduct);
100588b48caSValentina Manea 		usbip_names_get_class(class_name, sizeof(class_name),
101588b48caSValentina Manea 				      udev.bDeviceClass, udev.bDeviceSubClass,
102588b48caSValentina Manea 				      udev.bDeviceProtocol);
103588b48caSValentina Manea 		printf("%11s: %s\n", udev.busid, product_name);
104588b48caSValentina Manea 		printf("%11s: %s\n", "", udev.path);
105588b48caSValentina Manea 		printf("%11s: %s\n", "", class_name);
106588b48caSValentina Manea 
107588b48caSValentina Manea 		for (j = 0; j < udev.bNumInterfaces; j++) {
108588b48caSValentina Manea 			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
109588b48caSValentina Manea 			if (rc < 0) {
110588b48caSValentina Manea 				err("usbip_net_recv failed: usbip_usb_intf[%d]",
111588b48caSValentina Manea 						j);
112588b48caSValentina Manea 
113588b48caSValentina Manea 				return -1;
114588b48caSValentina Manea 			}
115588b48caSValentina Manea 			usbip_net_pack_usb_interface(0, &uintf);
116588b48caSValentina Manea 
117588b48caSValentina Manea 			usbip_names_get_class(class_name, sizeof(class_name),
118588b48caSValentina Manea 					uintf.bInterfaceClass,
119588b48caSValentina Manea 					uintf.bInterfaceSubClass,
120588b48caSValentina Manea 					uintf.bInterfaceProtocol);
121588b48caSValentina Manea 			printf("%11s: %2d - %s\n", "", j, class_name);
122588b48caSValentina Manea 		}
123588b48caSValentina Manea 
124588b48caSValentina Manea 		printf("\n");
125588b48caSValentina Manea 	}
126588b48caSValentina Manea 
127588b48caSValentina Manea 	return 0;
128588b48caSValentina Manea }
129588b48caSValentina Manea 
130588b48caSValentina Manea static int list_exported_devices(char *host)
131588b48caSValentina Manea {
132588b48caSValentina Manea 	int rc;
133588b48caSValentina Manea 	int sockfd;
134588b48caSValentina Manea 
135588b48caSValentina Manea 	sockfd = usbip_net_tcp_connect(host, usbip_port_string);
136588b48caSValentina Manea 	if (sockfd < 0) {
137588b48caSValentina Manea 		err("could not connect to %s:%s: %s", host,
138588b48caSValentina Manea 		    usbip_port_string, gai_strerror(sockfd));
139588b48caSValentina Manea 		return -1;
140588b48caSValentina Manea 	}
141588b48caSValentina Manea 	dbg("connected to %s:%s", host, usbip_port_string);
142588b48caSValentina Manea 
143588b48caSValentina Manea 	rc = get_exported_devices(host, sockfd);
144588b48caSValentina Manea 	if (rc < 0) {
145588b48caSValentina Manea 		err("failed to get device list from %s", host);
146588b48caSValentina Manea 		return -1;
147588b48caSValentina Manea 	}
148588b48caSValentina Manea 
149588b48caSValentina Manea 	close(sockfd);
150588b48caSValentina Manea 
151588b48caSValentina Manea 	return 0;
152588b48caSValentina Manea }
153588b48caSValentina Manea 
154588b48caSValentina Manea static void print_device(const char *busid, const char *vendor,
155588b48caSValentina Manea 			 const char *product, bool parsable)
156588b48caSValentina Manea {
157588b48caSValentina Manea 	if (parsable)
158588b48caSValentina Manea 		printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
159588b48caSValentina Manea 	else
160588b48caSValentina Manea 		printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
161588b48caSValentina Manea }
162588b48caSValentina Manea 
163588b48caSValentina Manea static void print_product_name(char *product_name, bool parsable)
164588b48caSValentina Manea {
165588b48caSValentina Manea 	if (!parsable)
166588b48caSValentina Manea 		printf("   %s\n", product_name);
167588b48caSValentina Manea }
168588b48caSValentina Manea 
169588b48caSValentina Manea static int list_devices(bool parsable)
170588b48caSValentina Manea {
171588b48caSValentina Manea 	struct udev *udev;
172588b48caSValentina Manea 	struct udev_enumerate *enumerate;
173588b48caSValentina Manea 	struct udev_list_entry *devices, *dev_list_entry;
174588b48caSValentina Manea 	struct udev_device *dev;
175588b48caSValentina Manea 	const char *path;
176588b48caSValentina Manea 	const char *idVendor;
177588b48caSValentina Manea 	const char *idProduct;
178588b48caSValentina Manea 	const char *bConfValue;
179588b48caSValentina Manea 	const char *bNumIntfs;
180588b48caSValentina Manea 	const char *busid;
181588b48caSValentina Manea 	char product_name[128];
182588b48caSValentina Manea 	int ret = -1;
183588b48caSValentina Manea 
184588b48caSValentina Manea 	/* Create libudev context. */
185588b48caSValentina Manea 	udev = udev_new();
186588b48caSValentina Manea 
187588b48caSValentina Manea 	/* Create libudev device enumeration. */
188588b48caSValentina Manea 	enumerate = udev_enumerate_new(udev);
189588b48caSValentina Manea 
190588b48caSValentina Manea 	/* Take only USB devices that are not hubs and do not have
191588b48caSValentina Manea 	 * the bInterfaceNumber attribute, i.e. are not interfaces.
192588b48caSValentina Manea 	 */
193588b48caSValentina Manea 	udev_enumerate_add_match_subsystem(enumerate, "usb");
194588b48caSValentina Manea 	udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
195588b48caSValentina Manea 	udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
196588b48caSValentina Manea 	udev_enumerate_scan_devices(enumerate);
197588b48caSValentina Manea 
198588b48caSValentina Manea 	devices = udev_enumerate_get_list_entry(enumerate);
199588b48caSValentina Manea 
200588b48caSValentina Manea 	/* Show information about each device. */
201588b48caSValentina Manea 	udev_list_entry_foreach(dev_list_entry, devices) {
202588b48caSValentina Manea 		path = udev_list_entry_get_name(dev_list_entry);
203588b48caSValentina Manea 		dev = udev_device_new_from_syspath(udev, path);
204588b48caSValentina Manea 
205588b48caSValentina Manea 		/* Get device information. */
206588b48caSValentina Manea 		idVendor = udev_device_get_sysattr_value(dev, "idVendor");
207588b48caSValentina Manea 		idProduct = udev_device_get_sysattr_value(dev, "idProduct");
208588b48caSValentina Manea 		bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue");
209588b48caSValentina Manea 		bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces");
210588b48caSValentina Manea 		busid = udev_device_get_sysname(dev);
211588b48caSValentina Manea 		if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
212588b48caSValentina Manea 			err("problem getting device attributes: %s",
213588b48caSValentina Manea 			    strerror(errno));
214588b48caSValentina Manea 			goto err_out;
215588b48caSValentina Manea 		}
216588b48caSValentina Manea 
217588b48caSValentina Manea 		/* Get product name. */
218588b48caSValentina Manea 		usbip_names_get_product(product_name, sizeof(product_name),
219588b48caSValentina Manea 					strtol(idVendor, NULL, 16),
220588b48caSValentina Manea 					strtol(idProduct, NULL, 16));
221588b48caSValentina Manea 
222588b48caSValentina Manea 		/* Print information. */
223588b48caSValentina Manea 		print_device(busid, idVendor, idProduct, parsable);
224588b48caSValentina Manea 		print_product_name(product_name, parsable);
225588b48caSValentina Manea 
226588b48caSValentina Manea 		printf("\n");
227588b48caSValentina Manea 
228588b48caSValentina Manea 		udev_device_unref(dev);
229588b48caSValentina Manea 	}
230588b48caSValentina Manea 
231588b48caSValentina Manea 	ret = 0;
232588b48caSValentina Manea 
233588b48caSValentina Manea err_out:
234588b48caSValentina Manea 	udev_enumerate_unref(enumerate);
235588b48caSValentina Manea 	udev_unref(udev);
236588b48caSValentina Manea 
237588b48caSValentina Manea 	return ret;
238588b48caSValentina Manea }
239588b48caSValentina Manea 
240588b48caSValentina Manea int usbip_list(int argc, char *argv[])
241588b48caSValentina Manea {
242588b48caSValentina Manea 	static const struct option opts[] = {
243588b48caSValentina Manea 		{ "parsable", no_argument,       NULL, 'p' },
244588b48caSValentina Manea 		{ "remote",   required_argument, NULL, 'r' },
245588b48caSValentina Manea 		{ "local",    no_argument,       NULL, 'l' },
246588b48caSValentina Manea 		{ NULL,       0,                 NULL,  0  }
247588b48caSValentina Manea 	};
248588b48caSValentina Manea 
249588b48caSValentina Manea 	bool parsable = false;
250588b48caSValentina Manea 	int opt;
251588b48caSValentina Manea 	int ret = -1;
252588b48caSValentina Manea 
253588b48caSValentina Manea 	if (usbip_names_init(USBIDS_FILE))
254588b48caSValentina Manea 		err("failed to open %s", USBIDS_FILE);
255588b48caSValentina Manea 
256588b48caSValentina Manea 	for (;;) {
257588b48caSValentina Manea 		opt = getopt_long(argc, argv, "pr:l", opts, NULL);
258588b48caSValentina Manea 
259588b48caSValentina Manea 		if (opt == -1)
260588b48caSValentina Manea 			break;
261588b48caSValentina Manea 
262588b48caSValentina Manea 		switch (opt) {
263588b48caSValentina Manea 		case 'p':
264588b48caSValentina Manea 			parsable = true;
265588b48caSValentina Manea 			break;
266588b48caSValentina Manea 		case 'r':
267588b48caSValentina Manea 			ret = list_exported_devices(optarg);
268588b48caSValentina Manea 			goto out;
269588b48caSValentina Manea 		case 'l':
270588b48caSValentina Manea 			ret = list_devices(parsable);
271588b48caSValentina Manea 			goto out;
272588b48caSValentina Manea 		default:
273588b48caSValentina Manea 			goto err_out;
274588b48caSValentina Manea 		}
275588b48caSValentina Manea 	}
276588b48caSValentina Manea 
277588b48caSValentina Manea err_out:
278588b48caSValentina Manea 	usbip_list_usage();
279588b48caSValentina Manea out:
280588b48caSValentina Manea 	usbip_names_free();
281588b48caSValentina Manea 
282588b48caSValentina Manea 	return ret;
283588b48caSValentina Manea }
284