Re: [PATCH v3 2/3] tools/usbip: export USB devices on a given bus persistently

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks for the comments, below are my responses.

On Wed, Oct 27, 2021 at 05:45:14PM -0600, Shuah Khan wrote:
> On 10/27/21 1:31 PM, Lars Gunnarsson wrote:
> > This patch extends the command "usbip bind" with flag "-p|--persistent". When
> > this flag is used, devices on a given busid becomes exported when plugged in,
> > instead of returning an error if the device is not available. When the usb
> > device is unplugged, it will start monitor the bus again.
> > 
> > Signed-off-by: Lars Gunnarsson <gunnarsson.lars@xxxxxxxxx>
> > ---
> > v2: Change title, fix style warnings, improve feature description, refactor
> >      cmdline flag usage.
> > v3: Change title and description.
> > 
> >   Documentation/usb/usbip_protocol.rst |   5 ++
> >   tools/usb/usbip/src/usbip_bind.c     | 114 +++++++++++++++++++++------
> >   2 files changed, 94 insertions(+), 25 deletions(-)
> > 
> > diff --git a/Documentation/usb/usbip_protocol.rst b/Documentation/usb/usbip_protocol.rst
> > index 0b8541fda4d8..2ed7d97278e8 100644
> > --- a/Documentation/usb/usbip_protocol.rst
> > +++ b/Documentation/usb/usbip_protocol.rst
> > @@ -9,6 +9,11 @@ The USB/IP protocol follows a server/client architecture. The server exports the
> >   USB devices and the clients import them. The device driver for the exported
> >   USB device runs on the client machine.
> > 
> > +Initially the server may choose to export any of its available USB devices,
> > +based on the busid. The device will remain exported until it's unplugged or
> > +unbound from the usbip driver. It is also possible to persistently export
> > +devices on a given bus by monitor when they are plugged in.
> > +
> >   The client may ask for the list of the exported USB devices. To get the list the
> >   client opens a TCP/IP connection to the server, and sends an OP_REQ_DEVLIST
> >   packet on top of the TCP/IP connection (so the actual OP_REQ_DEVLIST may be sent
> > diff --git a/tools/usb/usbip/src/usbip_bind.c b/tools/usb/usbip/src/usbip_bind.c
> > index f1cf9225a69c..fd4ccbfce6c6 100644
> > --- a/tools/usb/usbip/src/usbip_bind.c
> > +++ b/tools/usb/usbip/src/usbip_bind.c
> > @@ -8,12 +8,14 @@
> > 
> >   #include <errno.h>
> >   #include <stdio.h>
> > +#include <stdbool.h>
> >   #include <stdlib.h>
> >   #include <string.h>
> > 
> >   #include <getopt.h>
> > 
> >   #include "usbip_common.h"
> > +#include "usbip_monitor.h"
> >   #include "utils.h"
> >   #include "usbip.h"
> >   #include "sysfs_utils.h"
> > @@ -24,10 +26,17 @@ enum unbind_status {
> >   	UNBIND_ST_FAILED
> >   };
> > 
> > +struct bind_options {
> > +	char *busid;
> > +	bool is_persistent;
> > +};
> > +
> >   static const char usbip_bind_usage_string[] =
> >   	"usbip bind <args>\n"
> > -	"    -b, --busid=<busid>    Bind " USBIP_HOST_DRV_NAME ".ko to device "
> > -	"on <busid>\n";
> > +	"    -b, --busid=<busid>        Bind " USBIP_HOST_DRV_NAME ".ko to device\n"
> > +	"                               on <busid>\n"
> > +	"    -p, --persistent           Persistently monitor the given bus and\n"
> > +	"                               export USB devices plugged in\n";
> > 
> >   void usbip_bind_usage(void)
> >   {
> > @@ -127,29 +136,26 @@ static int unbind_other(char *busid)
> >   	return status;
> >   }
> > 
> > -static int bind_device(char *busid)
> > +static const char *get_device_devpath(char *busid)
> >   {
> > -	int rc;
> > -	struct udev *udev;
> > -	struct udev_device *dev;
> > -	const char *devpath;
> > +	struct udev *udev = udev_new();
> > +	const char *devpath = NULL;
> > +	struct udev_device *dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
> > 
> > -	/* Check whether the device with this bus ID exists. */
> > -	udev = udev_new();
> > -	dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
> > -	if (!dev) {
> > -		err("device with the specified bus ID does not exist");
> > -		return -1;
> > -	}
> > -	devpath = udev_device_get_devpath(dev);
> > +	if (dev)
> > +		devpath = udev_device_get_devpath(dev);
> >   	udev_unref(udev);
> > +	return devpath;
> > +}
> > 
> > -	/* If the device is already attached to vhci_hcd - bail out */
> > -	if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {
> > -		err("bind loop detected: device: %s is attached to %s\n",
> > -		    devpath, USBIP_VHCI_DRV_NAME);
> > -		return -1;
> > -	}
> > +static bool is_usb_connected(char *busid)
> > +{
> > +	return get_device_devpath(busid) != NULL;
> 
> Let's make this easier to read. I see what you are doing here.
> Just make it easier to read.

Does this make it more readable?

if (get_device_devpath(busid))
  return true;
else
  return false;

> 
> 
> > +}
> > +
> > +static int bind_available_device(char *busid)
> > +{
> > +	int rc;
> > 
> >   	rc = unbind_other(busid);
> >   	if (rc == UNBIND_ST_FAILED) {
> > @@ -174,36 +180,94 @@ static int bind_device(char *busid)
> >   		return -1;
> >   	}
> > 
> > -	info("bind device on busid %s: complete", busid);
> > +	info("device on busid %s: bind complete", busid);
> > 
> >   	return 0;
> >   }
> > 
> > +static int bind_device(char *busid)
> > +{
> > +	const char *devpath = get_device_devpath(busid);
> > +
> > +	/* Check whether the device with this bus ID exists. */
> > +	if (!devpath) {
> > +		err("device with the specified bus ID does not exist");
> > +		return -1;
> > +	}
> > +
> > +	/* If the device is already attached to vhci_hcd - bail out */
> > +	if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {
> > +		err("bind loop detected: device: %s is attached to %s\n",
> > +		    devpath, USBIP_VHCI_DRV_NAME);
> > +		return -1;
> > +	}
> > +
> > +	return bind_available_device(busid);
> > +}
> > +
> > +static int bind_device_persistently(char *busid)
> > +{
> > +	int rc = 0;
> > +	bool already_connected = is_usb_connected(busid);
> > +	usbip_monitor_t *monitor = monitor = usbip_monitor_new();
> > +
> > +	usbip_monitor_set_busid(monitor, busid);
> > +	while (rc == 0) {
> > +		if (!already_connected) {
> > +			info("device on busid %s: monitor connect", busid);
> > +			usbip_monitor_await_usb_bind(monitor, USBIP_USB_DRV_NAME);
> > +		}
> > +		rc = bind_available_device(busid);
> > +		if (rc == 0) {
> > +			info("device on busid %s: monitor disconnect", busid);
> > +			usbip_monitor_await_usb_bind(monitor, USBIP_HOST_DRV_NAME);
> > +			usbip_monitor_await_usb_unbind(monitor);
> > +		}
> > +		already_connected = false;
> > +	}
> > +	usbip_monitor_delete(monitor);
> > +	return rc;
> > +}
> > +
> >   int usbip_bind(int argc, char *argv[])
> >   {
> >   	static const struct option opts[] = {
> >   		{ "busid", required_argument, NULL, 'b' },
> > +		{ "persistent",  no_argument, NULL, 'p' },
> >   		{ NULL,    0,                 NULL,  0  }
> >   	};
> > 
> > +	struct bind_options options = {};
> >   	int opt;
> >   	int ret = -1;
> > 
> >   	for (;;) {
> > -		opt = getopt_long(argc, argv, "b:", opts, NULL);
> > +		opt = getopt_long(argc, argv, "b:p", opts, NULL);
> > 
> >   		if (opt == -1)
> >   			break;
> > 
> >   		switch (opt) {
> >   		case 'b':
> > -			ret = bind_device(optarg);
> > -			goto out;
> > +			options.busid = optarg;
> > +			break;
> > +		case 'p':
> > +			options.is_persistent = true;
> > +			break;
> >   		default:
> >   			goto err_out;
> >   		}
> >   	}
> > 
> > +	if (!options.busid)
> > +		goto err_out;
> > +
> > +	if (options.is_persistent)
> > +		ret = bind_device_persistently(options.busid);
> > +	else
> > +		ret = bind_device(options.busid);
> > +	goto out;
> > +
> >   err_out:
> >   	usbip_bind_usage();
> >   out:
> > --
> > 2.25.1
> > 
> > 
> 
> thanks,
> -- Shuah



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux