Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/usb/usbip/src/usbip_list.c
26288 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (C) 2011 matt mooney <[email protected]>
4
* 2005-2007 Takahiro Hirofuchi
5
* Copyright (C) 2015-2016 Samsung Electronics
6
* Igor Kotrasinski <[email protected]>
7
* Krzysztof Opasiak <[email protected]>
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
32
static 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
39
void usbip_list_usage(void)
40
{
41
printf("usage: %s", usbip_list_usage_string);
42
}
43
44
static 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
128
static 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
152
static 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
161
static void print_product_name(char *product_name, bool parsable)
162
{
163
if (!parsable)
164
printf(" %s\n", product_name);
165
}
166
167
static 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
242
err_out:
243
udev_enumerate_unref(enumerate);
244
udev_unref(udev);
245
246
return ret;
247
}
248
249
static 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
319
err_out:
320
udev_enumerate_unref(enumerate);
321
udev_unref(udev);
322
323
return ret;
324
}
325
326
int 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
367
err_out:
368
usbip_list_usage();
369
out:
370
usbip_names_free();
371
372
return ret;
373
}
374
375