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