Hi, Here's the updated patch against 2.6.16.2, which hopefully solves the issues that were pointed out. Except one thing: > You missed an update to drivers/usb/core/hub.c to the > configuration selection code ... it needs to know about > this new RNDIS variant, avoiding it if there's a standard > option.
Not sure what to do about this as these devices only have one configuration, so please forgive me if I've misunderstood horribly, which is quite likely. :) Regards, Ole André On 4/4/06, Ole André Vadla Ravnås <[EMAIL PROTECTED]> wrote: > Hi, > > Sorry about the late reply, work's been killing off most of my > spare-time lately. > > > Could you resend without line wraps etc? quoted-printable is > > evil for patches. Also, for my convenience in review, please > > pass the "p" flag to diff ("diff -Naurp") so I can see what > > procedures are being patched. Plus, the right place to post > > USB patches is [EMAIL PROTECTED] :) > > Ok, thanks, will do. I'll subscribe to that list as well and post the > revised patch there. :) > > > Do you have a URL for this specification? I only have the > > RNDIS 1.0 specification, you seem to have access to some > > sort of modified version ... maybe it fixes some of the holes > > in the 1.0 spec? Ditto the WM5 subclass and protocol ... those > > look like official USB-IF values, and last I checked there were > > no assigned values. > > Sorry, I've only got the 1.0 spec as well, I've basically > reverse-engineered my way to figuring out what the changes are. (Wrote > a quick 'n dirty app to help me comprehend the protocol: > http://projects.collabora.co.uk/~oleavr/usbhound.png). > > > You missed an update to drivers/usb/core/hub.c to the > > configuration selection code ... it needs to know about > > this new RNDIS variant, avoiding it if there's a standard > > option. > > Ah, I see. I'll fix this. > > > For rndis_host.c, please highlight that adding the extra 48 > > bytes is a requirement MSFT added after the RNDIS 1.0 spec. > > Good point! Noted. > > > For cdc_ether.c please make > > > > /* multiline comments end like > > * this > > */ > > > > instead of > > > > /* the wrong multiline comment > > * style */ > > Noted. > > > I'm glad to see this patch. That rndis_host driver has had > > relatively minimal testing against MSFT code ... so it's good > > to see that it's getting used! > > That's good to hear. Thanks for your most excellent work! I've only > received positive feedback from other users with WM5 devices so far, > so things are looking good. > > > Hmm, well http://www.usb.org/developers/defined_class > > says that there is a "misc" protocol for RNDIS, but it > > doesn't match the one you provided (that's for Bluetooth!) > > and there's no spec I can find ... > > Hmm, really? I've used base class 0xEF, sub-class 0x01 and protocol > 0x01, which is what is specified there (if I understood it correctly). > > I'll post a revised patch as soon as I get back to life (by the end of > the weekend or early next week). :) Thanks a lot for your time, most > appreciated. > > Regards, > Ole André >
diff -Naurp linux-2.6.16.2-orig/drivers/usb/net/cdc_ether.c linux-2.6.16.2/drivers/usb/net/cdc_ether.c --- linux-2.6.16.2-orig/drivers/usb/net/cdc_ether.c 2006-04-07 19:56:47.000000000 +0300 +++ linux-2.6.16.2/drivers/usb/net/cdc_ether.c 2006-04-10 01:03:10.000000000 +0300 @@ -72,7 +72,8 @@ int usbnet_generic_cdc_bind(struct usbne /* this assumes that if there's a non-RNDIS vendor variant * of cdc-acm, it'll fail RNDIS requests cleanly. */ - rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); + rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff || + intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_MISC); memset(info, 0, sizeof *info); info->control = intf; @@ -172,6 +173,61 @@ next_desc: buf += buf [0]; } + /* Windows Mobile 5 based RNDIS devices lack the CDC descriptors, + * so to work around this without changing too much of the overall + * logic we fake those headers here. + */ + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_MISC) { + struct usb_cdc_header_desc *h = NULL; + struct usb_cdc_union_desc *u = NULL; + + dev_dbg(&intf->dev, "taking WM5 workaround path\n"); + + /* allocate and fill the missing structures */ + h = kmalloc(sizeof(struct usb_cdc_header_desc), GFP_KERNEL); + u = kmalloc(sizeof(struct usb_cdc_union_desc), GFP_KERNEL); + if (!h || !u) { + if (h) + kfree(h); + if (u) + kfree(u); + + return -ENOMEM; + } + + info->header = h; + + h->bLength = sizeof(struct usb_cdc_header_desc); + h->bDescriptorType = USB_DT_CS_INTERFACE; + h->bDescriptorSubType = USB_CDC_HEADER_TYPE; + + h->bcdCDC = 0; + + info->u = u; + + u->bLength = sizeof(struct usb_cdc_union_desc); + u->bDescriptorType = USB_DT_CS_INTERFACE; + u->bDescriptorSubType = USB_CDC_UNION_TYPE; + + u->bMasterInterface0 = 0; + u->bSlaveInterface0 = 1; + + /* initialize */ + info->control = usb_ifnum_to_if(dev->udev, + info->u->bMasterInterface0); + info->data = usb_ifnum_to_if(dev->udev, + info->u->bSlaveInterface0); + if (!info->control || !info->data) { + dev_dbg(&intf->dev, + "master #%u/%p slave #%u/%p\n", + info->u->bMasterInterface0, + info->control, + info->u->bSlaveInterface0, + info->data); + goto bad_desc; + } + } + if (!info->header || !info->u || (!rndis && !info->ether)) { dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", info->header ? "" : "header ", @@ -229,6 +285,17 @@ void usbnet_cdc_unbind(struct usbnet *de struct cdc_state *info = (void *) &dev->data; struct usb_driver *driver = driver_of(intf); + /* clean up resources allocated by the Windows Mobile 5 + * RNDIS workaround ... + */ + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_MISC) { + if (info->header) + kfree(info->header); + + if (info->u) + kfree(info->u); + } + /* disconnect master --> disconnect slave */ if (intf == info->control && info->data) { /* ensure immediate exit from usbnet_disconnect */ diff -Naurp linux-2.6.16.2-orig/drivers/usb/net/rndis_host.c linux-2.6.16.2/drivers/usb/net/rndis_host.c --- linux-2.6.16.2-orig/drivers/usb/net/rndis_host.c 2006-04-07 19:56:47.000000000 +0300 +++ linux-2.6.16.2/drivers/usb/net/rndis_host.c 2006-04-10 00:55:29.000000000 +0300 @@ -377,6 +377,7 @@ static int rndis_bind(struct usbnet *dev struct rndis_set_c *set_c; } u; u32 tmp; + char *p; /* we can't rely on i/o from stack working, or stack allocation */ u.buf = kmalloc(1024, GFP_KERNEL); @@ -409,11 +410,18 @@ fail: dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu, 1 << le32_to_cpu(u.init_c->packet_alignment)); - /* get designated host ethernet address */ - memset(u.get, 0, sizeof *u.get); + /* get designated host ethernet address + * + * adding a payload exactly the same size as the expected + * response' payload is a requirement added by MSFT as of + * post-RNDIS 1.0 + */ + memset(u.get, 0, sizeof *u.get + 48); u.get->msg_type = RNDIS_MSG_QUERY; - u.get->msg_len = ccpu2(sizeof *u.get); + u.get->msg_len = ccpu2(sizeof *u.get + 48); u.get->oid = OID_802_3_PERMANENT_ADDRESS; + u.get->len = ccpu2(48); + u.get->offset = ccpu2(20); retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { @@ -575,10 +583,14 @@ static const struct driver_info rndis_in /*-------------------------------------------------------------------------*/ +#define WM5_SUB_CLASS 0x01 +#define WM5_PROTOCOL 0x01 + static const struct usb_device_id products [] = { { /* RNDIS is MSFT's un-official variant of CDC ACM */ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), + USB_INTERFACE_INFO(USB_CLASS_MISC, WM5_SUB_CLASS, WM5_PROTOCOL), .driver_info = (unsigned long) &rndis_info, }, { }, // END diff -Naurp linux-2.6.16.2-orig/include/linux/usb_ch9.h linux-2.6.16.2/include/linux/usb_ch9.h --- linux-2.6.16.2-orig/include/linux/usb_ch9.h 2006-04-07 19:56:47.000000000 +0300 +++ linux-2.6.16.2/include/linux/usb_ch9.h 2006-04-10 00:22:01.000000000 +0300 @@ -217,6 +217,7 @@ struct usb_device_descriptor { #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ #define USB_CLASS_VIDEO 0x0e #define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef #define USB_CLASS_APP_SPEC 0xfe #define USB_CLASS_VENDOR_SPEC 0xff