Mounting an iPod/iPhone on a Linux device

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

Looking for new projects

Now that the project in which I’ve been working for some time is completely functional and at the moment I’m not developing for it, I’m looking for new projects in the consumer equipment platforms field such as digital TV.

If you have an embedded Linux project or know someone who has, you can contact me at pedro (’dot’) aguilar (’dot’) iniestra (’at’) gmail (’dot’) com

QBoxHD and QBoxHD-mini sources released with ‘SDK’

Last year was a very busy year and I didn’t have much time for posting, but this year seems to be much better.
In fact, the first good news is that the QBoxHD Team released the source code of almost all the software that runs in these boxes.
If you want to see the sources right away, you can go the project’s homepage at SourceForge.
You can get the sources from the SVN repository:

svn co https://qboxhd.svn.sourceforge.net/svnroot/qboxhd/trunk  qboxhd

Some of the most important components were already OSS such as the kernel and the application software Enigma2, so they had to be released anyway. As a matter of fact, they were released several months ago, but they were never updated, although they were in an SVN repository. This was due to the team that worked in a private repository and never sync’ed to the public one.

Although Duolabs is doing a great effort for opening their development process (you can see that the SourceForge’s SVN repository is actively used), not all the software is being released. Some critical parts such as everything related to the FPGA remains proprietary.

However, most of the sources that before were proprietary, now are OSS released under the GPLv2. And this, along with a simple mechanism for compiling these sources, are the relevant part that could mean an advantage for these decoders.

Let’s start with the development environment.
It is a simple, yet useful system targeted for compiling the kernel, drivers and the middleware and application software. This environment is just a set of scripts that only allows to:

  • Compile the boot loader
  • Compile the kernel
  • Compile the drivers (only the OSS)
  • Compile enigma2 (middleware and application software)
  • Work with an NFS filesystem and an TFTP server
  • Create releases using the official procedure

These tools consist of a Makefile, a configuration file config.in and some other Shell and Perl scripts inside the /sdk directory. If you want to check the details you can have a look at the project’s wiki that is far from being complete, but at least it describes the basic procedure for compiling the mentioned sources.

It’s a quite simple set of tools. Thus, do not expect any development environment such as the ones used in projects like MeeGo or Android. Properly speaking, this is not an SDK, only a set of scripts that allows to build the sources and create a release almost identical to the official one.

These QboxHD tools were developed one bit at a time as requirements were added to the system and to fit the needs of a small team, taking into account that the development was done in a closed fashion, different from an open development that everybody can follow. I think that’s the reason why, in one hand, they have a specific and practical purpose, and in the other hand, are quite limited if compared to full-blown development environments.

It would be quite nice if this system was migrated to a real full-platform build tool such as Poky. Unfortunately, the SH4-based processors don’t have any support of this kind.

Now let’s move to the source code that was released.
Besides the already known OSS (U-Boot, Linux kernel and Enigma2), the relevant part is in the /src/drivers directory in which some of the drivers that previously were proprietary were now released under the GPLv2.
Inside this directory we get the following drivers:

  • avs
  • e2_proc
  • fpanel
  • frontends
  • includes
  • lcd
  • lpc
  • multicom
  • player2
  • qboxhd_generic
  • scart
  • stmfb

The drivers avs, e2_proc, includes, multicom, player2 and stmfb were basically taken from the sh4 duckbox project and STLinux and modified accordingly, so these are not really new.

The rest of the drivers are the ones used for controlling most of the decoder’s hardware. The hardware between both boards is quite different, so you’ll see specific drivers and/or macros that differentiate them.
Notice that all the drivers and applications regarding the FPGA inside these boxes remains strictly proprietary…

The fpanel is used for controlling the colours and behaviour of the sense-wheel and front-button of the QBoxHD and QBoxHD-mini, respectively. You can regulate the colours leds… nothing useful, but at least fun.

The lcd controls the front panel LCDs. Since they support at least 64k colours, you can display nice images although the data-transfer speed is not high.

The lpc is only present in the QBoxHD-mini and controls the Stand-By functionality.

The qboxhd_generic resets the tuners at boot time, boring…

The scart drivers controls the analog A/V outputs (SCART, components, composite and audio stereo). The digital video output (HDMI) is controlled by the stmfb driver that is part of the STLinux2.3 distribution.

The frontends directory contains the drivers for the DVB-S2/T/C tuners and pll’s. All of them are based on drivers taken from the mainline Linux kernel, except the DVB-S2 AVL2108 demod (with stv6306 pll) that was developed specifically for these decoders. I don’t know of any DVB-S2 PCI card or USB adapter that mounts this demod, because this driver could be re-used and maybe included in the mainline kernel.

Another interesting directory, specially for the people that wants to start playing around in userland, is the /src/apps directory in which several relatively simple applications such as display_image can be used as example for gaining confidence with the development for these decoders and, in general, with the embedded devices development.

In this directory you can find too the modified sources of Busybox and libdvbsi++ that are Open Source Projects.

As you can see, with all these sources licensed under the GPL, these decoders can be a good platform for people that want to start developing in user or kernel space with Embedded Linux and with a special focus in High Definition DVB devices.
Another benefit is that these boxes could become a reference point regarding openness in the High Definition DVB decoders market since these are basically the only decoders with almost all their sources available.

Openness is a factor that cannot be under estimated.