[PATCH] Add code to support USBIP Project for Windows

From: VizXu
Date: Mon Mar 18 2019 - 12:38:18 EST


Signed-off-by: VizXu <xujiweigo@xxxxxxx>
---
drivers/usb/usbip/stub_dev.c | 4 ++++
drivers/usb/usbip/stub_rx.c | 37 +++++++++++++++++++++++++++++++++++++
drivers/usb/usbip/usbip_common.h | 16 ++++++++++++++++
3 files changed, 57 insertions(+)

diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index c0d6ff1..be95c72 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -270,6 +270,10 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev)
sdev->ud.tcp_socket = NULL;
sdev->ud.sockfd = -1;

+#ifdef SUPPORT_WIN
+ sdev->ud.is_configured = false;
+#endif
+
INIT_LIST_HEAD(&sdev->priv_init);
INIT_LIST_HEAD(&sdev->priv_tx);
INIT_LIST_HEAD(&sdev->priv_free);
diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
index 97b09a4..8e004bc 100644
--- a/drivers/usb/usbip/stub_rx.c
+++ b/drivers/usb/usbip/stub_rx.c
@@ -11,6 +11,35 @@
#include "usbip_common.h"
#include "stub.h"

+#ifdef SUPPORT_WIN
+static int usbip_device_init_configuration(struct usbip_device *ud)
+{
+ struct usb_ctrlrequest req;
+ __u16 config;
+ int err;
+
+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+
+ struct usb_device *udev = sdev->udev;
+
+ req.bRequest = USB_REQ_SET_CONFIGURATION;
+ req.bRequestType = USB_RECIP_DEVICE;
+ req.wIndex = 0x00;
+ req.wLength = 0x00;
+ req.wValue = 0x01;
+ config = le16_to_cpu(req.wValue);
+
+ err = usb_set_configuration(udev, config);
+ if (err && err != -ENODEV) {
+ dev_err(&udev->dev, "%s can't set config\n", "usbip_device_init_configuration");
+ return -1;
+ }
+ ud->is_configured = true;
+
+ return 0;
+}
+#endif
+
static int is_clear_halt_cmd(struct urb *urb)
{
struct usb_ctrlrequest *req;
@@ -579,6 +608,14 @@ int stub_rx_loop(void *data)
{
struct usbip_device *ud = data;

+#ifdef SUPPORT_WIN
+ if (!ud->is_configured) {
+ if (-1 == usbip_device_init_configuration(ud)) {
+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+ }
+ }
+#endif
+
while (!kthread_should_stop()) {
if (usbip_event_happened(ud))
break;
diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
index bf8afe9..b5189e6 100644
--- a/drivers/usb/usbip/usbip_common.h
+++ b/drivers/usb/usbip/usbip_common.h
@@ -122,6 +122,17 @@ extern struct device_attribute dev_attr_usbip_debug;
#define USBIP_DIR_IN 0x01

/**
+* Support USBIP project for Windows: http://usbip.sourceforge.net/
+* The configuration is not initialized after an USB device bound in Linux
+* and that would make Linux kernel crash if usbip.exe attach it.
+* I've analysized this process with wireshark and found that usbip.exe
+* would not "SET CONFIGURATION Request". I suppose the process of loading
+* a USB device is different between Linux and Windows.
+* Make a usb_set_configuration at the first time would fix this issue.
+*/
+#define SUPPORT_WIN
+
+/**
* struct usbip_header_basic - data pertinent to every request
* @command: the usbip request type
* @seqnum: sequential number that identifies requests; incremented per
@@ -257,6 +268,11 @@ struct usbip_device {
spinlock_t lock;

int sockfd;
+
+#ifdef SUPPORT_WIN
+ bool is_configured;
+#endif
+
struct socket *tcp_socket;

struct task_struct *tcp_rx;
--
2.7.4