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