For a few weeks now, I’ve been trying to get my HTC Touch HD phone to work as a tethered (cos I haven’t bought a Bluetooth module for the laptop yet) RNDIS modem on Linux. I know it works great on Windows, but some for inexplicable reason connections would be fine on Linux for a minute or two, and then start timing out. ICMP worked great all the time, but SSH would only get a few lines, HTTP would get a few KB downloaded, etc. Rather infuriating.

Some investigation revealed the following in the output of dmesg when Internet Sharing was started up. Not very encouraging either, although it does give something to base a search on.

[ 5967.528071] usb 1-2: new high speed USB device using ehci_hcd and address 9
[ 5967.728209] usb 1-2: configuration #1 chosen from 1 choice
[ 5967.860790] rndis_host 1-2:1.0: dev can’t take 1536 byte packets (max 1536), adjusting MTU to 1478
[ 5967.870155] rndis_host 1-2:1.0: RNDIS_MSG_QUERY(0x00010202) failed, -47
[ 5967.892147] eth2: register ‘rndis_host’ at usb-0000:00:1d.7-2, RNDIS device, 80:00:60:0f:e8:00

After much fiddling around on forums, I came across the following solution…

Prepare your computer and build environment with the following

sudo apt-get install module-assistant
sudo module-assistant prepare

Next, download and patch the RNDIS code from the synce project.

mkdir ~/src ; cd ~/src
svn co http://synce.svn.sourceforge.net/svnroot/synce/trunk/usb-rndis-lite
cd usb-rndis-lite/

Now, a slight change has to be made to rndis_host.c. This can be done with gedit, vim, or any other text editor. Simply enclose goto fail in a comment, and put retval = -EINVAL; in instead :-)

gedit rndis_host.c

This is a diff file from after the change has been made.

root@x300:/usr/src/usb-rndis-lite# svn diff !$
svn diff rndis_host.c
Index: rndis_host.c
===================================================================
— rndis_host.c (revision 3769)
+++ rndis_host.c (working copy)
@@ -525,7 +525,8 @@
dev_err(&intf->dev,
“dev can’t take %u byte packets (max %u)\n”,
dev->hard_mtu, tmp);
– goto fail;
+ retval = -EINVAL;
+ /* goto fail; */
}

/* REVISIT: peripheral “alignment” request is ignored … */
root@x300:/usr/src/usb-rndis-lite#

Save the file and exit the text editor, and then build the source code. Once the build is complete, it can be installed as well.

make
sudo make install

The make install process will also run depmod, but you may have the rndis and cdc modules already loaded. You can either unload them with rmmod, or simply reboot.

All being well, you should see the following shortly after you start up Internet Sharing on your Windows Mobile phone.

[ 7192.121685] usb 1-2: new high speed USB device using ehci_hcd and address 14
[ 7192.307745] usb 1-2: configuration #1 chosen from 1 choice
[ 7192.402114] usbcore: registered new interface driver cdc_ether
[ 7192.824058] rndis_host 1-2:1.0: dev can’t take 1558 byte packets (max 1536)
[ 7194.070474] rndis0: register ‘rndis_host’ at usb-0000:00:1d.7-2, RNDIS device (SynCE patched), 80:00:60:0f:e8:00
[ 7194.072045] usbcore: registered new interface driver rndis_host

Test it out with a few websites and downloads. Remember, don’t go crazy unless you have an unlimited data plan ;-)