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