Merge tag 'for-linus-20190524' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / tools / usb / usbip / src / usbip_list.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
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
38 void usbip_list_usage(void)
39 {
40         printf("usage: %s", usbip_list_usage_string);
41 }
42
43 static 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
127 static 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
151 static 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
160 static void print_product_name(char *product_name, bool parsable)
161 {
162         if (!parsable)
163                 printf("   %s\n", product_name);
164 }
165
166 static 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
241 err_out:
242         udev_enumerate_unref(enumerate);
243         udev_unref(udev);
244
245         return ret;
246 }
247
248 static 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
318 err_out:
319         udev_enumerate_unref(enumerate);
320         udev_unref(udev);
321
322         return ret;
323 }
324
325 int 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
366 err_out:
367         usbip_list_usage();
368 out:
369         usbip_names_free();
370
371         return ret;
372 }