Projects‎ > ‎

iPhone USB Tethering in Linux

<current status: not yet working>

All current solutions for tethering iPhone in Linux use either Bluetooth or a WiFi / SSH combination. See http://xn--9bi.net/2009/06/17/tethering-iphone-3-0-to-ubuntu-9-04/ for an example.
After reading a lot of pages on iPhone Tethering, it turns out that the best method is using the USB cable.
Naturally, this works seamlessly on my wife's MacBook with my jailbroken 3GS. However, my main system runs Linux, how do I manage USB tethering there?
The story below show my efforts in trying to get this to work. It assumes basic Linux knowledge, and the fact that you have enabled iPhone's native tethering option.

Linux + iPhone USB Research

Some research shows that tethering enables a certain USB profile on the phone. You can see the phone connected by using lsusb as root:
obelix:~ # lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 04b3:4485 IBM Corp. Serial Converter
Bus 001 Device 005: ID 0424:2504 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 006: ID 046d:0a04 Logitech, Inc. V20 portable speakers (USB powered)
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 005: ID 05ac:1294 Apple, Inc.
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
...snip...

Zooming in on the iPhone, you can get a lot of information on the different configurations that are supported. One of the Configuration Descriptors mentions "Apple USB Ethernet":
obelix:~ # lsusb -d 05ac:1294 -v                                                  

Bus 002 Device 005: ID 05ac:1294 Apple, Inc.
Device Descriptor:                          
  bLength                18                 
  bDescriptorType         1                 
  bcdUSB               2.00                 
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0                            
  bDeviceProtocol         0                            
  bMaxPacketSize0        64                            
  idVendor           0x05ac Apple, Inc.                
  idProduct          0x1294                            
  bcdDevice            0.01                            
  iManufacturer           1 Apple Inc.                 
  iProduct                2 iPhone                     
  iSerial                 3 70ffc2f22fc4729a04e8eb1afadce41dfd020d5f
  bNumConfigurations      4
...snip...
  Configuration Descriptor:                                          
    bLength                 9                                        
    bDescriptorType         2                                        
    wTotalLength           94                                        
    bNumInterfaces          3                                        
    bConfigurationValue     4                                        
    iConfiguration          8 PTP + Apple Mobile Device + Apple USB Ethernet
    bmAttributes         0xc0                                              
      Self Powered                                                         
    MaxPower              500mA                                            
    Interface Descriptor:                                                  
...snip...

So the device is properly recognized, our main challenge is to enable Linux to use that configuration. During some research, I came across several people saying that for USB tethering you will need a device driver for Linux.
As a side note, they mentioned that windows + iTunes are capable of USB tethering already. So... has Apple written a windows network driver? And... can this be used in Linux using ndiswrapper?

Unpacking the Windows driver

In this tutorial we will need a windows machine to extract the Apple iPhone network driver from the iTunes installation files. It's quite trivial if you're familiar with windows installation methods. Below is a step-by-step guide on how to do this.
Note: if you are running
  • First download iTunes for windows from http://www.apple.com/itunes/download .
  • Then empty your Temp folder in C:\Documents and Settings\<username>\Local Settings\Temp to enable you to see the extracted iTunes files.
  • Start the installation using iTunesSetup.exe
  • Go to your Temp folder and locate the new directory that has been created. It should be named something like IXP304.TMP or similar.
  • From that directory, copy the file "AppleMobileDeviceSupport.msi" to another directory, we will use C:\temp
  • Cancel the iTunes installer.
Now we have the installation file with the Apple configuration and drivers for its mobile devices. Next step is to extract the iPhone network driver from it.
  • Open a windows command shell and go to the directory where you placed the msi file (here C:\temp)
  • Create a new directory for the extracted files: mkdir extract
  • Extract the msi with the following command: msiexec /a AppleMobileDeviceSupport.msi /qb C:\temp\extract
  • You will find the Apple network driver under c:\temp\extract\Common Files\Apple\Mobile Device Support\NetDrivers
  • Using any method, copy the NetDrivers directory and its contents to your Linux box
  • Get rid of the horrible windows machine. What did you have it for in the first place?
Using the driver with ndiswrapper

So your Linux will have to have ndiswrapper installed on it. Do this using your system's package manager. This research was done using openSUSE 11.2, where ndiswrapper is available in YaST.
  • Go into the NetDrivers directory on your Linux box
  • Edit the file netaapl.inf and correct the comma in line 19: %Aapl% = Aapl.NTx86  [ instead of %Aapl% = Aapl,NTx86 ]
  • Install the driver in ndiswrapper: ndiswrapper -i netaapl.inf
obelix:~/Apple/NetDrivers # ndiswrapper -i netaapl.inf
installing netaapl ...
  • Now plug in your iPhone and enable tethering. You can check the driver status with ndiswrapper -l:
obelix:~/Apple/NetDrivers # ndiswrapper -l
netaapl : driver installed
        device (05AC:1294) present
  • You are now readyto load ndiswrapper: modprobe ndiswrapper . Your iPhone will light up and beep.
  • If all went well, you have a new network interface to configure. Else, your error is probably in dmesg.

64Bit Installation

On 64Bit Linux this poses somewhat of a challenge. The reason is that iTunes 64Bit only comes with Ndis6 drivers using Windows Driver Foundation (WDF).
  • if you are running 64-bit Linux, you will need the 64-bit iTunes version from http://support.apple.com/kb/DL925 .
  • Installer program is called "iTunes64Setup.exe". The msi you need is called "AppleMobileDeviceSupport64.msi".
  • extract the msi using a different commandline: msiexec /a AppleMobileDeviceSupport64.msi /qb
  • The files will be extracted to C:\Common Files
  • Edit the netaapl64.inf file, change line 19 to %Aapl% = Aapl.NTAMD64
  • Try to install the driver with current ndiswrapper: ndiswrapper -i netaapl64.inf
  • Load ndiswrapper kernel module: modprobe ndiswrapper . See dmesg for the error: 
[89442.193368] ndiswrapper version 1.56 loaded (smp=yes, preempt=yes)
[89442.303160] usb 2-1: reset high speed USB device using ehci_hcd and address 9
[89442.423548] ndiswrapper (import:233): unknown symbol: WDFLDR.SYS:'WdfVersionBind'
[89442.423583] ndiswrapper (import:233): unknown symbol: WDFLDR.SYS:'WdfVersionUnbind'
[89442.423605] ndiswrapper (load_sys_files:206): couldn't prepare driver 'netaapl64'
[89442.424188] ndiswrapper (load_wrap_driver:108): couldn't load driver netaapl64; check system log for messages from 'loadndisdriver'
[89442.424311] usbcore: registered new interface driver ndiswrapper

As you can see it seems to fail on WDF support. We can try this with the new 1.6 release of ndiswrapper (called ndis6wrapper) which is supposed to support newer Vista drivers.
  • Install development tools on linux
  • install kernel source, kernel syms
  • on openSUSE: cd /usr/src/linux; make cloneconfig; make prepare; make modules_prepare
  • Link build directory for your kernel source: ln -s /usr/src/linux /lib/modules/<kernel>/build
  • Get the new ndis6 version of ndiswrapper: svn co https://ndiswrapper.svn.sourceforge.net/svnroot/ndiswrapper/branches/ndisv6/ndiswrapper
  • Make the new ndis6wrapper version: make; make install
  • Install the 64 bit driver: ndis6wrapper -i netaapl64.inf 
  • Load ndiswrapper: modprobe ndis6wrapper . See dmesg for the error:
[90451.166277] ndiswrapper version 1.99alpha loaded (smp=yes, preempt=yes)
[90451.281088] usb 2-1: reset high speed USB device using ehci_hcd and address 10
[90451.400862] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisAllocatePacketPool'
[90451.400908] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisAllocatePacket'
[90451.400940] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisFreeBufferPool'
[90451.400971] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisFreePacket'
[90451.401032] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisMIndicateStatus'
[90451.401065] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisMIndicateStatusComplete'
[90451.401115] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisFreePacketPool'
[90451.401151] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisAllocateBuffer'
[90451.401184] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisMRegisterMiniport'
[90451.401243] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisMRegisterUnloadHandler'
[90451.401295] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisMSetAttributesEx'
[90451.401333] ndiswrapper (import:236): unknown symbol: NDIS.SYS:'NdisAllocateBufferPool'
[90451.401379] ndiswrapper (import:236): unknown symbol: WDFLDR.SYS:'WdfVersionBind'
[90451.401409] ndiswrapper (import:236): unknown symbol: WDFLDR.SYS:'WdfVersionUnbind'
[90451.401430] ndiswrapper (load_sys_files:206): couldn't prepare driver 'netaapl64'
[90451.402483] ndiswrapper (load_wrap_driver:108): couldn't load driver netaapl64; check system log for messages from 'loadndis6driver'
[90451.402579] usbcore: registered new interface driver ndiswrapper


Comments