Linux Audio

Check our new training course

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