summaryrefslogtreecommitdiff
path: root/drivers/staging/usbip/userspace/src/usbip_list.c
diff options
context:
space:
mode:
authormatt mooney <mfm@muteddisk.com>2011-05-26 13:17:11 (GMT)
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 20:56:12 (GMT)
commite9837bbb3e694eef4c55c934ebf1f8a0399b142c (patch)
tree06cbd21cd4dd8b5aa2899e8f156221878e66761e /drivers/staging/usbip/userspace/src/usbip_list.c
parent58058422f84523d8ab73b98753670dc9377e071a (diff)
downloadlinux-fsl-qoriq-e9837bbb3e694eef4c55c934ebf1f8a0399b142c.tar.xz
staging: usbip: userspace tools v1.0.0
The new and improved (well somewhat, with a ways to go) userspace utility. mfm:pts/8[~/tmp/userspace] May26 05:18:31 % ./src/usbip help usage: usbip [--debug] [version] [help] <command> <args> attach Attach a remote USB device detach Detach a remote USB device list List exported or local USB devices bind Bind device to usbip-host.ko unbind Unbind device from usbip-host.ko This first commit of the userspace `usbip' utility uses to same implementation as the old tools, `usbip' and `usbip_bind_driver'. Nothing significant has changed so compatibility with windows has _not_ been broken. However, the tools remain broken in many ways due to the old implementation. Signed-off-by: matt mooney <mfm@muteddisk.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/usbip/userspace/src/usbip_list.c')
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_list.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c
new file mode 100644
index 0000000..72236ae
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_list.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ * 2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sysfs/libsysfs.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <dirent.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <regex.h>
+#include <unistd.h>
+
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "utils.h"
+#include "usbip.h"
+
+static const char usbip_list_usage_string[] =
+ "usbip list [-p|--parsable] <args>\n"
+ " -p, --parsable Parsable list format\n"
+ " -r, --remote=<host> List the exported USB devices on <host>\n"
+ " -l, --local List the local USB devices\n";
+
+void usbip_list_usage(void)
+{
+ printf("usage: %s", usbip_list_usage_string);
+}
+
+static int query_exported_devices(int sockfd)
+{
+ int ret;
+ struct op_devlist_reply rep;
+ uint16_t code = OP_REP_DEVLIST;
+
+ memset(&rep, 0, sizeof(rep));
+
+ ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
+ if (ret < 0) {
+ err("send op_common");
+ return -1;
+ }
+
+ ret = usbip_recv_op_common(sockfd, &code);
+ if (ret < 0) {
+ err("recv op_common");
+ return -1;
+ }
+
+ ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
+ if (ret < 0) {
+ err("recv op_devlist");
+ return -1;
+ }
+
+ PACK_OP_DEVLIST_REPLY(0, &rep);
+ dbg("exportable %d devices", rep.ndev);
+
+ for (unsigned int i=0; i < rep.ndev; i++) {
+ char product_name[100];
+ char class_name[100];
+ struct usb_device udev;
+
+ memset(&udev, 0, sizeof(udev));
+
+ ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
+ if (ret < 0) {
+ err("recv usb_device[%d]", i);
+ return -1;
+ }
+ pack_usb_device(0, &udev);
+
+ usbip_names_get_product(product_name, sizeof(product_name),
+ udev.idVendor, udev.idProduct);
+ usbip_names_get_class(class_name, sizeof(class_name),
+ udev.bDeviceClass, udev.bDeviceSubClass,
+ udev.bDeviceProtocol);
+
+ printf("%8s: %s\n", udev.busid, product_name);
+ printf("%8s: %s\n", " ", udev.path);
+ printf("%8s: %s\n", " ", class_name);
+
+ for (int j=0; j < udev.bNumInterfaces; j++) {
+ struct usb_interface uinf;
+
+ ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
+ if (ret < 0) {
+ err("recv usb_interface[%d]", j);
+ return -1;
+ }
+
+ pack_usb_interface(0, &uinf);
+ usbip_names_get_class(class_name, sizeof(class_name),
+ uinf.bInterfaceClass,
+ uinf.bInterfaceSubClass,
+ uinf.bInterfaceProtocol);
+
+ printf("%8s: %2d - %s\n", " ", j, class_name);
+ }
+
+ printf("\n");
+ }
+
+ return rep.ndev;
+}
+
+static int show_exported_devices(char *host)
+{
+ int ret;
+ int sockfd;
+
+ sockfd = usbip_net_tcp_connect(host, USBIP_PORT_STRING);
+ if (sockfd < 0) {
+ err("unable to connect to %s port %s: %s\n", host,
+ USBIP_PORT_STRING, gai_strerror(sockfd));
+ return -1;
+ }
+ dbg("connected to %s port %s\n", host, USBIP_PORT_STRING);
+
+ printf("- %s\n", host);
+
+ ret = query_exported_devices(sockfd);
+ if (ret < 0) {
+ err("query");
+ return -1;
+ }
+
+ close(sockfd);
+ return 0;
+}
+
+static int is_usb_device(char *busid)
+{
+ int ret;
+
+ regex_t regex;
+ regmatch_t pmatch[1];
+
+ ret = regcomp(&regex, "^[0-9]+-[0-9]+(\\.[0-9]+)*$", REG_NOSUB|REG_EXTENDED);
+ if (ret < 0)
+ err("regcomp: %s\n", strerror(errno));
+
+ ret = regexec(&regex, busid, 0, pmatch, 0);
+ if (ret)
+ return 0; /* not matched */
+
+ return 1;
+}
+
+static int show_devices(void)
+{
+ DIR *dir;
+
+ dir = opendir("/sys/bus/usb/devices/");
+ if (!dir)
+ err("opendir: %s", strerror(errno));
+
+ printf("List USB devices\n");
+ for (;;) {
+ struct dirent *dirent;
+ char *busid;
+
+ dirent = readdir(dir);
+ if (!dirent)
+ break;
+
+ busid = dirent->d_name;
+
+ if (is_usb_device(busid)) {
+ char name[100] = {'\0'};
+ char driver[100] = {'\0'};
+ int conf, ninf = 0;
+ int i;
+
+ conf = read_bConfigurationValue(busid);
+ ninf = read_bNumInterfaces(busid);
+
+ getdevicename(busid, name, sizeof(name));
+
+ printf(" - busid %s (%s)\n", busid, name);
+
+ for (i = 0; i < ninf; i++) {
+ getdriver(busid, conf, i, driver,
+ sizeof(driver));
+ printf(" %s:%d.%d -> %s\n", busid, conf,
+ i, driver);
+ }
+ printf("\n");
+ }
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+static int show_devices2(void)
+{
+ DIR *dir;
+
+ dir = opendir("/sys/bus/usb/devices/");
+ if (!dir)
+ err("opendir: %s", strerror(errno));
+
+ for (;;) {
+ struct dirent *dirent;
+ char *busid;
+
+ dirent = readdir(dir);
+ if (!dirent)
+ break;
+
+ busid = dirent->d_name;
+
+ if (is_usb_device(busid)) {
+ char name[100] = {'\0'};
+ char driver[100] = {'\0'};
+ int conf, ninf = 0;
+ int i;
+
+ conf = read_bConfigurationValue(busid);
+ ninf = read_bNumInterfaces(busid);
+
+ getdevicename(busid, name, sizeof(name));
+
+ printf("busid=%s#usbid=%s#", busid, name);
+
+ for (i = 0; i < ninf; i++) {
+ getdriver(busid, conf, i, driver, sizeof(driver));
+ printf("%s:%d.%d=%s#", busid, conf, i, driver);
+ }
+ printf("\n");
+ }
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+int usbip_list(int argc, char *argv[])
+{
+ static const struct option opts[] = {
+ { "parsable", no_argument, NULL, 'p' },
+ { "remote", required_argument, NULL, 'r' },
+ { "local", no_argument, NULL, 'l' },
+ { NULL, 0, NULL, 0 }
+ };
+ bool is_parsable = false;
+ int opt;
+ int ret = -1;
+
+ if (usbip_names_init(USBIDS_FILE))
+ err("failed to open %s\n", USBIDS_FILE);
+
+ for (;;) {
+ opt = getopt_long(argc, argv, "pr:l", opts, NULL);
+
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'p':
+ is_parsable = true;
+ break;
+ case 'r':
+ ret = show_exported_devices(optarg);
+ goto out;
+ case 'l':
+ if (is_parsable)
+ ret = show_devices2();
+ else
+ ret = show_devices();
+ goto out;
+ default:
+ goto err_out;
+ }
+ }
+
+err_out:
+ usbip_list_usage();
+out:
+ usbip_names_free();
+
+ return ret;
+}