PTP Solution

Upgrading the PTP Support on CentOS 6

Introduction

I picked up the Nikon D7100 a few weeks ago to suppress my amateur photography needs. A long story short: my new camera isn’t recognized in CentOS 6. After much Googling, I found out the problem lies in the libgphoto2 library which grants PTP support to Linux. CentOS/RHEL 6 ships with the libgphoto2 library at version 2.4.7 and the Nikon D7100 isn’t supported with it until version 2.5.2.

So then… just upgrade; what’s the big deal?

It wasn’t that simple unfortunately but it was the starting point. In fact grabbing the latest (already) packaged source from our friendly Fedora (20) distribution and rebuilding it for our environment was the first approach.

Then following issues then surfaced:

  • The version of GVfs that ships with CentOS/RHEL 6 is compiled against the old libgphoto2. As a result, I needed to re-compile this package against the new version of libphoto2. I also needed to create a patch to accommodate the changes that reside in the libgphoto2 library.

Enough talking; just give me the goods.

You can scroll to the bottom of this blog for information on how to install these packages onto your system if your not familiar with the task at hand.

Binary Packages

Source Packages

I don’t trust you; I’d like to do it myself

I was prepared for this; just to cover myself until I gain your trust, here is what I did:

First I set up a mock environment to work in; this allows us to do compiling outside of our native environment and means we don’t need to ever install any development libraries.

First prepare our development environment with mock if you haven’t already:

# Install 'mock' into your environment if you don't have it already
# This step will require you to be the superuser (root) in your native
# environment.
yum install -y mock

# Grant your normal every day user account access to the mock group
# This step will also require you to be the root user.
usermod -a -G mock YourNonRootUsername

At this point we can get away from the root user and build using our own user we created for our system.

# Download the official libgphoto2 packages from their official
# hosting site:
wget http://downloads.sourceforge.net/project/gphoto/libgphoto/2.5.2/libgphoto2-2.5.2.tar.bz2
wget http://downloads.sourceforge.net/project/gphoto/gphoto/2.5.2/gphoto2-2.5.2.tar.bz2

# Download the source rpms
wget --output-document=gphoto2-2.5.2-3.el6.src.rpm https://www.dropbox.com/sh/9dt7klam6ex1kpp/MN-ZInf7cl/20131007/ptp/gphoto2-2.5.2-3.el6.src.rpm?dl=1
wget --output-document=libgphoto2-2.5.2-1.el6.src.rpm https://www.dropbox.com/sh/9dt7klam6ex1kpp/FZv_8wmpka/20131007/ptp/libgphoto2-2.5.2-1.el6.src.rpm?dl=1

# Initialize our Environment
mock -v -r epel-6-x86_64 --init

# Just install the nessisary dependencies
mock -v -r epel-6-x86_64 --installdeps libgphoto2-2.5.2-1.el6.src.rpm

# readline-devel is required by gphoto2, but we can't use the
# --installdeps flag because another dependency is libgphoto2
# which we haven't built yet... that will come later.  Just type
# the following command to speed up and simplify this tutorial
mock -v -r epel-6-x86_64 --install readline-devel

# Copy our packages into our environment
mock -v -r epel-6-x86_64 --copyin 
   gphoto2-2.5.2.tar.bz2 
   libgphoto2-2.5.2.tar.bz2 
   gphoto2-2.5.2-3.el6.src.rpm 
   libgphoto2-2.5.2-1.el6.src.rpm 
   /builddir/build

# Shell into our enviroment
mock -v -r epel-6-x86_64 --shell

# Change to our build directory
cd builddir/build

# You're now in the build environment within the mock environment.
# If you type the following, you should 'only' see the 2 RPMs we
# copied into here in addition of the the 2 .tar.bz2 files we
# downloaded from sourceforge.
find -type f

# You can confirm that you do infact have properly formatted source
# rpms by executing the following:
rpm -qlp gphoto2-2.5.2-3.el6.src.rpm libgphoto2-2.5.2-1.el6.src.rpm

# You're going to install the src.rpm's now.  Don't worry; this is
# safe to do since src.rpm's don't contain executable scripts.
# Instead they'll just distribute the files you saw in the above
# command within the SPEC, and SOURCE directory you see infront of
# you into the '/builddir/build' directory.
rpm -Uhi gphoto2-2.5.2-3.el6.src.rpm libgphoto2-2.5.2-1.el6.src.rpm

# You can see how the files were distributed using the find command
# above we specified earlier
find -type f

# There is no magic here; we basically just extracted the gphoto
# packages
#
# The only reason I took you this far is so you can see there is
# nothing Place the .tar.bz2 files you downloaded over the ones
# provided so you're confident I haven't introduced something you're
# not expecting. The following command will overwrite the files
# provided in the src.rpm with the fresh ones you downloaded from
# the website.
mv -f *.tar.bz2 SOURCES

# Inspect anything your uncertain of... such as the patches I ported
# from earlier versions. Feel free to download the previous version
# and compare.
less SOURCES/gphoto2-cjc-device-return.patch
less SOURCES/gphoto2-cjc-pkgcfg.patch
less SOURCES/gphoto2-cjc-storage.patch

# Inspect the SPEC file (which is a copy from the v2.4.7 version
# with all patches ported forward)
less SPECS/libgphoto2.spec

# There aren't any chages made to this spec file but have a look
# anyway if you like
less SPECS/gphoto2.spec

# Once your satisfied; build the libgphoto2 rpm first; it won't take
# too long (maybe 5 minutes or so)
rpmbuild -ba SPECS/libgphoto2.spec

# When this is done you'll have several RPMS built
find RPMS SRPMS -type f

# We need to install the libgphoto2-devel and libgphoto2 into our mock
# environment as they are required to build the gphoto2 package
rpm -Uhi RPMS/libgphoto2-devel-2.5.2-1.el6.x86_64.rpm 
         RPMS/libgphoto2-2.5.2-1.el6.x86_64.rpm

# Now we can build gphoto2 (this goes really fast - 10 seconds or so)
rpmbuild -ba SPECS/gphoto2.spec

# we're now done with our mock environment for now; Press Ctrl-D to
# exit or simply type exit on the command line of our virtual
# environment
exit

# We'll return to the directory we were previously in.  We can copy
# out the packages we just built at this point.Ignore the warning
# about SELinux if you get one. It doesn't impact our goals at this
# moment.
mock -v -r epel-6-x86_64 --copyout /builddir/build/SRPMS/gphoto2-2.5.2-3.el6.src.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/SRPMS/libgphoto2-2.5.2-1.el6.src.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gphoto2-2.5.2-3.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gphoto2-debuginfo-2.5.2-3.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/libgphoto2-2.5.2-1.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/libgphoto2-debuginfo-2.5.2-1.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/libgphoto2-devel-2.5.2-1.el6.x86_64.rpm .

GVfs can provide an easy mountable filesystem out of the PTP protocol for those who don’t like the Command Line Interface (CLI) gphoto2 provides. For those who think they’ll use it (or already are) can now recompile it against the new library we just built along with a small patch file to make it possible. The patch is already prepared in the source rpm I provide in the example below. If you wish to download the GVfs source that ships with CentOS instead; consider that it won’t compile right out of the box with libgphoto2 without the patch I backported from a newer distribution. You can skip this if you don’t use GVfs.

# Initialize our Environment
mock -v -r epel-6-x86_64 --init

# Install the only dependency we know mock can't otherwise fetch
# externally since it's sitting right here in front of us
mock -v -r epel-6-x86_64 --install 
   libgphoto2-2.5.2-1.el6.x86_64.rpm 
   libgphoto2-devel-2.5.2-1.el6.x86_64.rpm

# Download the version of gvfs that includes the patch I created
wget --output-document=gvfs-1.4.3-16.el6.src.rpm https://www.dropbox.com/sh/9dt7klam6ex1kpp/n-cFArw3i4/20131007/ptp/gvfs-1.4.3-16.el6.src.rpm?dl=1

# GVfs has one problem... it won't compile against the new libraries
# and design offered by the latest version of libgphoto2. I've already
# modified it to handle the patch (112) and incremented the build so
# it can easily built onto your system.
mock -v -r epel-6-x86_64 --installdeps gvfs-1.4.3-16.el6.src.rpm
mock -v -r epel-6-x86_64 --copyin gvfs-1.4.3-16.el6.src.rpm /builddir/build

# Shell into our environment
mock -v -r epel-6-x86_64  --shell

# Change to our build directory
cd builddir/build/

# Install our Source RPM (you can refer to the above section if you
# feel the need to inspect the contents first)
rpm -Uhi gvfs-1.4.3-16.el6.src.rpm

# Here is your chance to preview the patch (112) i put in place as well as
# the SPEC file that I updated to accomodate it.
less SOURCES/gvfs-1.4.3-gphoto25-support.patch
less SPECS/gvfs.spec

# Build GVFS
rpmbuild -ba SPECS/gvfs.spec

# we're now done with our mock environment for now; Press Ctrl-D to
# exit or simply type exit on the command line of our virtual
# environment
exit

# We'll return to the directory we were previously in.  We can copy out
# the packages we just built at this point (ignore the Warning about
# SELinux if you get one. It doesn't impact our goals at this moment.
mock -v -r epel-6-x86_64 --copyout /builddir/build/SRPMS/gvfs-1.4.3-16.el6.src.rpm .

mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-devel-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-obexftp-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-fuse-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-debuginfo-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-archive-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-afc-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-gphoto2-1.4.3-16.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/gvfs-smb-1.4.3-16.el6.x86_64.rpm .

SANE backends grants access to your scanner software you may or may not be using. It tool will have to be recompiled if you were using it as it links to the gphoto2 libraries. You can skip this if you don’t use the backend.

# Initialize our Environment
mock -v -r epel-6-x86_64 --init

# Install the only dependancy we know mock can't otherwise fetch
# externally since it's sitting right here infront of us
mock -v -r epel-6-x86_64 --install 
   libgphoto2-2.5.2-1.el6.x86_64.rpm 
   libgphoto2-devel-2.5.2-1.el6.x86_64.rpm

# Download the sane-backends package
wget --output-document=sane-backends-1.0.21-4.el6.src.rpm https://www.dropbox.com/sh/9dt7klam6ex1kpp/v5VyYHjsUu/20131007/ptp/sane-backends-1.0.21-4.el6.src.rpm

# Prepare the environment to support the sane-backend libraries
# You should be noticing a trend now as to how we're getting
# all the compilation and setup done.
mock -v -r epel-6-x86_64 --installdeps sane-backends-1.0.21-4.el6.src.rpm
mock -v -r epel-6-x86_64 --copyin sane-backends-1.0.21-4.el6.src.rpm /builddir/build

# Install our Source RPM (you can refer to the above section if you
# feel the need to inspect the contents first)
rpm -Uhi sane-backends-1.0.21-4.el6.src.rpm

# The only change I made to the SPEC file was to increment the build #
# so it would link properly back to our libgphoto2 libraries.
# Thankfully there is no patch need here.
less SPECS/sane-backends.spec

# Build GVFS
rpmbuild -ba SPECS/sane-backends.spec

# we're now done with our mock environment for now; Press Ctrl-D to
# exit or simply type exit on the command line of our virtual
# environment
exit

# We'll return to the directory we were previously in.  We can copy out
# the packages we just built at this point (ignore the Warning about
# SELinux if you get one. It doesn't impact our goals at this moment.
mock -v -r epel-6-x86_64 --copyout /builddir/build/SRPMS/sane-backends-1.0.21-4.el6.src.rpm .

mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/sane-backends-devel-1.0.21-4.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/sane-backends-1.0.21-4.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/sane-backends-libs-gphoto2-1.0.21-4.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/sane-backends-libs-1.0.21-4.el6.x86_64.rpm .
mock -v -r epel-6-x86_64 --copyout /builddir/build/RPMS/sane-backends-debuginfo-1.0.21-4.el6.x86_64.rpm .

You are now all done with the building!

Installation

You can upgrade/install your system with these new packages through the following (or variations of) commands:

# You may need to tailor the lower line depending what you have
# installed on your system. In my case, I also use the smb package
# where as you might not.  You can remove that from the line below
# if you wish.
yum localinstall libgphoto2-2.5.2-1.el6.x86_64.rpm gphoto2-2.5.2-3.el6.x86_64.rpm 
   gvfs-1.4.3-16.el6.x86_64.rpm gvfs-fuse-1.4.3-16.el6.x86_64.rpm 
   gvfs-gphoto2-1.4.3-16.el6.x86_64.rpm gvfs-smb-1.4.3-16.el6.x86_64.rpm 
   gvfs-archive-1.4.3-15.el6.x86_64

# in fact; if you want be really clever, I suppose you could do
# it like this:

# The following will loop the rpms we built and prepare a yum
# upgrade command for you
PKGS=$(find . -mindepth 1 -maxdepth 1 -type f -name '*.rpm' ! -name '*.src.rpm' -exec rpm -qp --queryformat="{}|%{NAME} " {} 😉
FILES=""
for PKG in $PKGS; do
   FILE=$(echo $PKG | cut -f1 -d'|')
   ID=$(echo $PKG | cut -f2 -d'|')
   rpm -q $ID &>/dev/null
   [ $? -eq 0 ] && FILES="$FILES $FILE"
done
echo "$FILES" | egrep -q "gphoto2"
if [ $? -ne 0 ]; then
   echo "Note: You're not using gphoto2 at all right now."
   FILES="$FILES libgphoto2-2.5.2-1.el6.x86_64.rpm gphoto2-2.5.2-3.el6.x86_64.rpm"
fi
echo "Type the following to upgrade/install it into your system:"
echo "  yum localinstall $FILES"

GPhoto2 CLI Reference

Just a script file I created and keep in ($HOME/bin) for myself to simplify extracting content from my camera when I connect it.

#!/bin/sh
# Script: getPhotos.sh
# Author: Chris Caron
# Date: Oct 7th, 2013
# Desc: Just a really simple tool for extracting all of the
#       images off of the camera based on the date you run
#       it.
PHOTOALBUM="$HOME/Nikon"
NOW=$(date +'%Y-%m-%d')

[ ! -d "$PHOTOALBUM/$NOW" ] && mkdir -p "$PHOTOALBUM/$NOW"
pushd "$PHOTOALBUM/$NOW" && gphoto2 --get-all-files
if [ $? -eq 0 ]; then
  # Transfer went okay; We need the recurse entry so we look
  # past the / directory
  gphoto2 --delete-all-files --recurse
fi
popd &>/dev/null

But it’s really worth checking out all the great options and examples gphoto2 offers if you choose to use it. The man pages show all of the other options supported; it truely is a fantastic tool!

Credit

Please note that this information took me several days to put together and test thoroughly. I may not blog often; but I want to re-assure the stability and testing I put into everything I intend share.

If you like what you see and wish to copy and paste this HOWTO, please reference back to this blog post at the very least. It’s really all I ask.

Sources

  • I used pkgs.org to obtain rpm source packaging for libgphoto2, gphoto2, gvfs, and sane-backends so I could rebuild with content that was already stable and tested.
  • The gphoto official website was a great source of information as to how to utilize their tool and explain how it works.
  • I can’t find the examples I found for the GVfs patch I wrote at the time. But Googling for it now turns up many results of people who have done the same thing. Although at the time I regret not tracking the source I used as reference; you will see a similar patch here. Keep in mind this link is again nothing but a reference; it patches a newer version of GVfs over the one shipped with CentOS and RHEL. If you choose to use it over mine; you’ll need to read from it and rebuild the patch file yourself. It will definitely not work as is.

Leave a Reply

Your email address will not be published. Required fields are marked *