These days mounting an iPod/iPhone/iPad on a Linux PC is an automatic task and all the synchronization operations, such as the music sync with Rythmbox, are supported or at least partially supported.
The communication with these devices can take place thanks to the libimobiledevice library with the help of fuse (filesystem in userspace) and several other libraries and applications. For a clearer picture of the involved libraries you can have a look at this software stack diagram.
Unfortunately, having the same functionality in a Linux embedded device such as a Set-Top-Box or a Digital Receiver is not easy because all the applications are part or depend strongly on GNOME or KDE that normally are not available in these systems.
However, all the libraries can be cross-compiled allowing to mount an iPod/iPhone/iPad as a storage device.
Of course, if you want to synchronize your data such as music or videos, you’ll have to develop your own application or port an existing one.
In this post I focus only on how to compile all the required libraries for mounting an iPod/iPhone/iPad as a storage device.
If the Set-Top-Box have a media player with the required codecs, they will be able, at least, to play the content.
Requirements
Fuse needs a kernel driver that is already included in the mainline kernel. In the kernel configuration you find this option under the Filesystem menu. You can compile it as a module or in-kernel. If you choose the former, the module will be called fuse.ko.
Environment configuration
Suppose that we want to install all the libraries in /mnt/target/usr/local.
/mnt/target is the top directory of the target’s filesystem that could be mounted via NFS.
Assume that the cross-toolchain (compiler, linker…) is already in your path.
Set the following environment variables:
$ export PREFIX=/mnt/target/usr/local
$ export HOST=sh4-linux
$ export BUILD=i386-linux
$ export LD_LIBRARY_PATH=$PREFIX/lib
$ export PKG_CONFIG_PATH=$LD_LIBRARY_PATH/pkgconfig
libusb
Package: libusb-1.0.8.tar.bz2
This package is required by libimobiledevice.
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX --disable-static --disable-log
$ make
$ make install
libplist
Package: libplist-1.3.tar.bz2
This package is required by libimobiledevice.
The compilation of libplist is different because it uses cmake.
Create a file toolchain.cmake with the following contents. Modify the cross-compiler variables according to your path:
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER /opt/STM/STLinux-2.3/devkit/sh4/bin/sh4-linux-gcc)
SET(CMAKE_CXX_COMPILER /opt/STM/STLinux-2.3/devkit/sh4/bin/sh4-linux-g++)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /mnt/target/usr/local)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Then create the build directory, compile and install:
$ mkdir build
$ cd build
$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ..
$ make DESTDIR=$PREFIX install
usbmuxd
Package: usbmuxd-1.0.4.tar.bz2
This package is needed by libimobiledevice.
usbmux uses cmake too. Therefore, the procedure is the same as liplist:
Create the file toolchain.cmake with the same contents as with libplist-1.3 or just copy it to the current directory usbmuxd-1.0.4.
$ cd usbmuxd-1.0.4
$ cp ../libplist-1.3/toolchain.cmake .
Then create the build directory, compile and install:
$ mkdir build
$ cd build
$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ..
$ make DESTDIR=$PREFIX install
libgpg-error
Package: libgpg-error-1.7.tar.gz
This package is needed by libgcrypt.
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
$ make
$ make install
libgcrypt
Package: libgcrypt-1.4.6.tar.gz
This package is needed by gnutls
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX --with-gpg-error-prefix=$PREFIX
Note: I didn’t need to modify these Makefiles when using an updated STLinux2.3. But if you haven’t done an ‘stmyum update’ lately, maybe you’ll need to modify them.
Edit the Makefile:
Remove from the variables DIST_SUBDIRS and SUBDIRS the directory ‘tests’
Edit the src/Makefile:
Set the following variables to the given values:
GPG_ERROR_CFLAGS = /mnt/target/usr/local/include
GPG_ERROR_CONFIG =
GPG_ERROR_LIBS = /mnt/target/usr/local/lib/libgpg-error.so.0.7.0
libgcrypt_la_LIBADD =
../cipher/libcipher.la
../random/librandom.la
../mpi/libmpi.la
/mnt/target/usr/local/lib/libgpg-error.so.0.7.0
Compile and install:
$ make
$ make install
libtans1
Package: libtasn1-2.7.tar.gz
This package is needed by libimobiledevice.
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
$ make
$ make install
gnutls
Package: gnutls-2.8.6.tar.bz2
This package is needed by libimobiledevice.
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
--with-libgcrypt-prefix=$PREFIX --enable-large_files --disable-gtk-doc-html
Edit the files src/Makefile, doc/Makefile and doc/examples/Makefile:
Set LDFLAGS to this value:
LDFLAGS = /mnt/target/usr/local/lib/libgcrypt.so /mnt/target/usr/local/lib/libgpg-error.so
$ make
$ make install
libimobiledevice
Package: libimobiledevice-1.0.2.tar.bz2
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
libusbmuxd_CFLAGS="-I$PREFIX/include" libusbmuxd_LIBS="-L$PREFIX/lib"
libgnutls_CFLAGS="-I$PREFIX/include" libgnutls_LIBS="-L$PREFIX/lib"
libtasn1_CFLAGS="-I$PREFIX/include" libtasn1_LIBS="-L$PREFIX/lib"
libplist_CFLAGS="-I$PREFIX/include" libplist_LIBS="-L$PREFIX/lib"
libglib2_CFLAGS="-I$PREFIX/include -I$PREFIX/lib/glib-2.0/include" libglib2_LIBS="-L$PREFIX/lib"
--without-swig
Edit the file tools/Makefile:
Set LDFLAGS to this value:
LDFLAGS = /mnt/target/usr/local/lib/libgcrypt.so /mnt/target/usr/local/lib/libgpg-error.so /mnt/target/usr/local/lib/libplist.so /mnt/target/usr/local/lib/libtasn1.so /mnt/target/usr/local/lib/libusbmuxd.so /mnt/target/usr/local/lib/libgnutls.so
Compile and install:
$ make
$ make install
fuse
Package: fuse-2.8.4
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
$ make
$ make DESTDIR=$PREFIX install
ifuse
Package: ifuse-1.0.0.tar.bz2
$ ./configure --build=$BUILD --host=$HOST --prefix=$PREFIX
CFLAGS=-D_FILE_OFFSET_BITS=64
libimobiledevice_CFLAGS="-I$PREFIX/include" libimobiledevice_LIBS="-L$PREFIX/lib"
libglib2_CFLAGS="-I$PREFIX/include/glib-2.0 -I$PREFIX/lib/glib-2.0/include" libglib2_LIBS="-L$PREFIX/lib"
libgthread2_CFLAGS="-I$PREFIX/include" libgthread2_LIBS="-L$PREFIX/lib"
libfuse_CFLAGS="-I$PREFIX/include" libfuse_LIBS="-L$PREFIX/lib"
Edit the file src/Makefile:
Set libfuse_LIBS to this value:
libfuse_LIBS = -L/mnt/target/usr/local/lib -lfuse -limobiledevice -lgnutls -lplist -lusbmuxd
Compile and install:
$ make
$ make install
Mounting the device
At this point you should be able to mount your iPod/iPhone as a storage device. Some iPods can have a partition, like /dev/sda1, formatted as VFAT of HFS+, depending on where you use it. Some others, like the iPod shuffle, doesn’t have a partition, so you’ll see them as /dev/sda.
Assuming that you want to mount it in /media/ipod, that it has partition /dev/sdb1, and it’s formatted in VFAT, you can mount it as a normal storage device:
$ mount -t vfat -o usefree /dev/sdb1 /media/ipod
For HFS+ is the same. Notice that your kernel must be compiled for supporting this filesystem:
$ mount -t hfsplus -o ro /dev/sdb1 /media/ipod
Now you can browse in /media/ipod and you’ll see the contents of your iPod’s filesystem!
References