Hi,

While I was trying to make my WM5/smartphone work with Linux, 
I stumbled on problems as described in Bug 8094 
(http://bugzilla.kernel.org/show_bug.cgi?id=8094).

While studying this I think I found a problem in usbnet explaining why 
the synce WM5 patch 
(http://synce.svn.sourceforge.net/svnroot/synce/trunk/patches/linux-2.6.22-rndis_host-wm5.patch)
was required to get my phone connected.

The above WM5 patch is believed to be inadequate for memory constraint
system (as I learned in the Bug 8094 discussion). But this patch might not 
be needed if the patch I am proposing here is applied to usbnet. I already
proposed my patch in Bug 8094 but as I didn't receive any comment I 
decided to redo it on the list (Sorry if that was not the right decision)

Here is the description of the problem (copy/paste form Bug 8094):

When the rndis_host bind() function is called (by usbnet_probe()) the 
dev->maxpacket is not yet set (It will be set later in usbnet_probe()). 
As it is 0 the computed dev->rx_urb_size is also 0 and therefore the 
"max_transfer_size" sent to the device in the RNDIS_MSG_INIT message 
is also 0. I am not sure how the device will react to this but obviously 
this is a bogus value.

So it seems dev->maxpacket needs to be set before calling the bind() 
function (it makes some sense as rndis_bind() is using it). This means 
we need to move up the call to usb_maxpacket() in the  usbnet_probe()
function. But the call to usb_maxpacket() is requiring dev->out to be set 
which in turn requires this computation to be moved above the call to 
usb_maxpacket() (by the way I am not sure dev->out is set correctly 
with the actual version of the driver in case of a bind() device)

I am attaching a proposal for a patch to fix this problem (assuming I 
didn't overlook anything). With this patch the dev->rx_urb_size and the 
"max_transfer_size" are computed to 1600 with my device (qtek 9100) 
which seems reasonable enough. More importantly this works for me and 
I am able to communicate with the smartphone (without changing 
rndis_host.c with the wm5 patch).

Any comment is welcome.

JC

Signed-off-by: Jean-Christophe Dubois <[EMAIL PROTECTED]>
---

diff -ruN linux-source-2.6.24/drivers/net/usb/usbnet.c 
linux-source-2.6.24.new/drivers/net/usb/usbnet.c
--- linux-source-2.6.24/drivers/net/usb/usbnet.c        2008-01-24 
11:52:31.000000000 +0100
+++ linux-source-2.6.24.new/drivers/net/usb/usbnet.c    2008-02-05 
23:02:51.000000000 +0100
@@ -90,8 +90,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* handles CDC Ethernet and many other network "bulk data" interfaces */
-int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
+static struct usb_host_interface *usbnet_get_in_out(struct usbnet *dev, struct 
usb_interface *intf)
 {
        int                             tmp;
        struct usb_host_interface       *alt = NULL;
@@ -137,7 +136,28 @@
                if (in && out)
                        break;
        }
+
        if (!alt || !in || !out)
+               return NULL;
+
+       dev->in = usb_rcvbulkpipe (dev->udev,
+                       in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       dev->out = usb_sndbulkpipe (dev->udev,
+                       out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       dev->status = status;
+
+       return alt;
+}
+
+/* handles CDC Ethernet and many other network "bulk data" interfaces */
+int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
+{
+       int                             tmp;
+       struct usb_host_interface       *alt;
+
+       alt = usbnet_get_in_out(dev, intf);
+
+       if (!alt) 
                return -EINVAL;
 
        if (alt->desc.bAlternateSetting != 0
@@ -148,11 +168,6 @@
                        return tmp;
        }
 
-       dev->in = usb_rcvbulkpipe (dev->udev,
-                       in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-       dev->out = usb_sndbulkpipe (dev->udev,
-                       out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-       dev->status = status;
        return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_get_endpoints);
@@ -1191,6 +1206,15 @@
        net->tx_timeout = usbnet_tx_timeout;
        net->ethtool_ops = &usbnet_ethtool_ops;
 
+       if (info->out && info->in) {
+               dev->in = usb_rcvbulkpipe (dev->udev, info->in);
+               dev->out = usb_sndbulkpipe (dev->udev, info->out);
+       } else {
+               interface = usbnet_get_in_out(dev, udev);
+       }
+               
+       dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
+
        // allow device-specific bind/init procedures
        // NOTE net->name still not usable ...
        if (info->bind) {
@@ -1211,8 +1235,6 @@
        } else if (!info->in || !info->out)
                status = usbnet_get_endpoints (dev, udev);
        else {
-               dev->in = usb_rcvbulkpipe (xdev, info->in);
-               dev->out = usb_sndbulkpipe (xdev, info->out);
                if (!(info->flags & FLAG_NO_SETINT))
                        status = usb_set_interface (xdev,
                                interface->desc.bInterfaceNumber,
@@ -1228,7 +1250,6 @@
 
        if (!dev->rx_urb_size)
                dev->rx_urb_size = dev->hard_mtu;
-       dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
 
        SET_NETDEV_DEV(net, &udev->dev);
        status = register_netdev (net);
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to