As USB is designed for hotplugging of devices, the operating system also needs a mechanism that dynamically creates devices (device files) for the devices currently connected and switched on.
The operating system has to determine which users may access a device dynamically. As the operating system cannot determine this by itself, there have to be some helper applications.
If you are using pre-built packages for your distribution
(such as SuSE or Redhat RPMs or Debian
DEBs, Gentoo Ebuilds, FreeBSD pots, ...),
simply installing those packages should do this configuration
for you. In reality, however, you often still have to do a
varying amount of work. Read the documentation for your
package (usually somewhere in
/usr/share/doc/*gphoto2*/
) and this guide
section to find out if and what work there still is or may be
to do for you.
If you are installing and setting up libgphoto2 yourself, then the following sections explain the configuration of these helpers.
This section is currently (2006-12) under review. However, with the old text being so outdated, we have decided to publish this work in progress as-is. Slightly disorganized but accurate information is more useful than horribly outdated one.
The Linux Kernel contains both generic USB interface drivers and higher level USB device drivers for some devices like USB mice or USB thumb drivers. The generic interface drivers can be used from user space applications to connect to USB devices not specifically supported by the kernel itself. Any application using libgphoto2 is an example of such a user space application.
Unfortunately, for some devices there are drivers both in the kernel and in libgphoto2, creating a conflict situation. If that happens with your device and you want to use libgphoto2 instead of the kernel driver, you may have a problem. In later kernels and current libusb versions , libgphoto2 will try to unload the kernel driver for the interface as soon as libgphoto2 wants to claim the device. On older kernels, you need to prevent the kernel from loading its kernel space driver in some fashion.
Hotplugging of devices is a central feature of USB, and thus the Linux Kernel's USB system must also handle the addition of new devices at run-time. Over the course of time, multiple solutions for this have been invented: linux-hotplug (kernels 2.4), udev (kernel 2.6), and nowadays HAL (which provides complete desktop integration). The basic mechanism is the same: When the Kernel notices that a new USB device has been plugged in (or switched on), it runs a program. That program can then walk through its configured set of rules and apply them to the new device.
This section describes how to set up USB device permissions using HAL. Due to this article's author's cluelessness about HAL, it just describes the HAL setup provided by the Fedora Core 6 (FC6) gphoto2 RPM package.
The libgphoto2 specific part of the HAL configuration consists of two parts: The device list and a policy. Each is stored in its own file.
The device list file contains a list of all devices supported by libgphoto2 in any fashion and giving HAL information as to the device's capabilities. You can generate this file using the print-camera-list utility shipped with libgphoto2:
host:~#
/usr/lib/libgphoto2/print-camera-list hal-fdi > libgphoto2.fdi
The FC6 gphoto2 package stores this file
as
/usr/share/hal/fdi/information/20thirdparty/10-camera-libgphoto2.fdi
.
Its content looks like:
<?xml version="1.0" encoding="ISO-8859-1"?> <!-- -*- SGML -*- --> <!-- This file was generated by libgphoto2 print-camera-list - - fdi --> <deviceinfo version="0.2"> <device> <match key="info.bus" string="usb"> <match key="usb.vendor_id" int="1363"> <match key="usb.product_id" int="514"> <merge key="info.category" type="string">camera</merge> <append key="info.capabilities" type="strlist">camera</append> <merge key="camera.access_method" type="string">proprietary</merge> <merge key="camera.libgphoto2.name" type="string">AEG Snap 300</merge> <merge key="camera.libgphoto2.support" type="bool">true</merge> </match> </match> ... <match key="usb.vendor_id" int="10096"> <match key="usb.product_id" int="36956"> <merge key="info.category" type="string">camera</merge> <append key="info.capabilities" type="strlist">camera</append> <merge key="camera.access_method" type="string">proprietary</merge> <merge key="camera.libgphoto2.name" type="string">Vivitar Vivicam35</merge> <merge key="camera.libgphoto2.support" type="bool">true</merge> </match> </match> </match> </device> </deviceinfo>
Note that FC6's hal
RPM already ships the following
/usr/share/hal/fdi/information/10freedesktop/10-camera-ptp.fdi
file which matches all PTP class cameras,
so their being missing in the device list file generated by
print-camera-list does not matter:
<?xml version="1.0" encoding="UTF-8"?> <deviceinfo version="0.2"> <device> <match key="info.bus" string="usb"> <match key="usb.interface.class" int="0x06"> <match key="usb.interface.subclass" int="0x01"> <match key="usb.interface.protocol" int="0x01"> <merge key="info.category" type="string">camera</merge> <append key="info.capabilities" type="strlist">camera</append> <merge key="camera.access_method" type="string">ptp</merge> </match> </match> </match> </match> </device> </deviceinfo>
The policy file defines what HAL is to do
with devices which have a "camera" capability. The
FC6 gphoto2 package stores the policy
file as
/usr/share/hal/fdi/policy/20thirdparty/90-gphoto-camera-policy.fdi
.
It just calls a script, as the content shows:
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- --> <deviceinfo version="0.2"> <device> <match key="info.capabilities" contains="camera"> <match key="camera.access_method" string="proprietary"> <append key="info.callouts.add" type="strlist">/usr/libexec/gphoto-set-procperm</append> </match> <match key="camera.access_method" string="ptp"> <append key="info.callouts.add" type="strlist">/usr/libexec/gphoto-set-procperm</append> </match> </match> </device> </deviceinfo>
The FC6 gphoto2 package stores the
permission setup script as
/usr/libexec/gphoto-set-procperm
. It
uses printf(1) to
construct the name of the device file from
USB bus and device numbers given by
HAL, waits a few seconds to make sure the
device file actually exists, and then finally hands
ownership of the device file to the pam_console user:
#!/bin/bash console_user=`cat /var/run/console/console.lock` if [ -z "$console_user" ] ; then exit 1 fi if [ -z "$HAL_PROP_USB_BUS_NUMBER" -o -z "$HAL_PROP_USB_LINUX_DEVICE_NUMBER" ] ; then exit 2 fi if [ $HAL_PROP_USB_BUS_NUMBER -lt 0 -o $HAL_PROP_USB_LINUX_DEVICE_NUMBER -lt 0 ] ; then exit 3 fi bus_num=`printf %.3u $HAL_PROP_USB_BUS_NUMBER` dev_num=`printf %.3u $HAL_PROP_USB_LINUX_DEVICE_NUMBER` NUM_TRIES_LEFT=5 while [ $NUM_TRIES_LEFT -ge 0 ] && [ ! -c /dev/bus/usb/$bus_num/$dev_num ]; do sleep 1 NUM_TRIES_LEFT=$(($NUM_TRIES_LEFT - 1)) done [ -c /dev/bus/usb/$bus_num/$dev_num ] || exit 4 chown $console_user /dev/bus/usb/$bus_num/$dev_num NUM_TRIES_LEFT=5 while [ $NUM_TRIES_LEFT -ge 0 ] && [ ! -f /proc/bus/usb/$bus_num/$dev_num ]; do sleep 1 NUM_TRIES_LEFT=$(($NUM_TRIES_LEFT - 1)) done [ -f /proc/bus/usb/$bus_num/$dev_num ] || exit 5 chown $console_user /proc/bus/usb/$bus_num/$dev_num
udev
is the mechanism called by Linux Kernel 2.6 to add and
remove device files in /dev
. udev is an
integral part of the system, and thus installed directly in
/
, not in
/usr/
. This means that helper programs
and scripts are installed in /lib/udev/
,
and the udev rules are stored in
/etc/udev/rules.d/
.
There are multiple versions of udev around with slightly
different rule formats, so libgphoto2's
/usr/lib/libgphoto2/print-camera
supports a version
argument.
# call script /lib/udev/foobarhost:~#
/usr/lib/libgphoto2/print-camera-list \ udev-rules version 0.98 script foobar \ > /etc/udev/rules.d/90-libgphoto2.rules
# call script /path/to/foobarhost:~#
/usr/lib/libgphoto2/print-camera-list \ udev-rules version 0.98 script /path/to/foobar \ > /etc/udev/rules.d/90-libgphoto2.rules
# set up permissions with "chmod 0660 $device; chgrp plugdev $device"host:~#
/usr/lib/libgphoto2/print-camera-list \ udev-rules version 0.98 group plugdev mode 0660 \ > /etc/udev/rules.d/90-libgphoto2.rules
These udev rule files contain two sorts of matches: Lots of
listings by USB VendorID/ProductID, and
one special case each for matching PTP
and MTP devices. These two special cases
run special scripts/programs, which should also be installed
in /lib/udev/
.
#!/bin/sh # UNTESTED SCRIPT (but you get the idea) test "x$ACTION" != "xadd" || exit 0 test "x$SUBSYSTEM" != "xusb_device" || exit 0 if test -e "$DEVNAME" then user="photoripper" chown "$user" "$DEVNAME" chmod 0600 "$DEVNAME" # SUBSYSTEM == "usb_device" implies that DEVNAME == "/dev/bus/usb/123/456" # Determine device ID and bus ID. dev="$(basename "$DEVNAME")" bus="$(basename "$(dirname "$DEVNAME")")" # Download all files from that camera to incoming directory with # lowercase filenames command="/usr/bin/gphoto2 --port usb:${bus},${dev} --get-all-files" command="$command --filename /var/local/photodump/incoming/%:" echo "Executing command: $command" su "$photoripper" -c "$command" else echo "photoripper: Given device named $DEVNAME not found." exit 1 fi
linux-hotplug was the first solution for hooks to run when hotplugging devices, introduced with the 2.4 kernel's USB code.
linux-hotplug stores its files in pairs: One file
/etc/hotplug/usb/
is a list of device descriptions, and the other
usbcam
.usermap/etc/hotplug/usb/
is a script to call in
case a newly added device matches that description.
usbcam
libgphoto2 supports linux-hotplug via a device list
generated using print-camera-list and a
few example scripts shipped in
packaging/linux-hotplug/
.
host:~#
/usr/lib/libgphoto2/print-camera-list usb-usermap \ >
/etc/hotplug/usb/
usbcam
.usermap
In ancient times, before the arrival of udev, one usually
needed to mount the "usbdevfs" or later "usbfs" to
/proc/bus/usb
. One particular mount
option allowed the whole usb filesystem (i.e. all mice, card
readers, and all other USB devices) to be
made group or world writeable.
Obviously, this kind of “security” is no security and should thus be avoided. Additionally, since udev exists now, just use udev. You can look up how to shoot yourself in the foot with usbdevfs... where? Well, just use udev. After all, this is almost the year 2007, not 1997.
libgphoto2 provides a user space driver for cameras, which
conflicts with having a kernel driver for the camera.
So in order to use libgphoto2, you have to disable all kernel drivers which want
to handle the camera themselves (e.g. the Linux
dc2xx
or
stv680
drivers). You can check whether these modules are loaded by
executing lsmod.
We will not cover basic USB setup in detail here. For more information on how to get USB working on your hardware and your system at all, we'd like to refer you to http://www.linux-usb.org/USB-guide/ and especially http://www.linux-usb.org/USB-guide/c122.html . These pages explains the USB basics in a better way than we could do.
Now that you've got your basic USB system working, you have basically two options to allow user access to USB devices on your Linux system:
/proc/bus/usb
[1]
with adequate user and/or group permissions (default
is world-readable and root-only-writable, which is good)
/proc/bus/usb
mounted here as well, but not mounted writable by
anybody else than root)
Solution b has a huge advantage over solution a: It doesn't allow the user/group to interfere with or eavesdrop on any other USB devices which might be attached, such as USB keyboards, fingerprint reader or similar. The following section thus describe setting up b.
On Linux systems, from the 2.4 kernel series on, the kernel supports hotplugging. You may have to compile a kernel with hotplug support if you're not already running one. You may have to install the hotplug package (http://linux-hotplug.sourceforge.net/) if you don't have it installed already.
Note (TODO). print-usb-usermap is deprecated as of 2.1.99.1. Use print-camera-list instead. Description of udev rules and HAL setup missing here.
To find out whether your kernel has hotplug support,
look for the file
/proc/sys/kernel/hotplug
.
If it exists, your kernel is hotplug enabled. If
alice@host:~$
cat
/proc/sys/kernel/hotplug
prints the path to your hotplug binary (usually /sbin/hotplug) and this binary exists, you are ready to rock.
Also note that the following solution does
not
provide absolute security and that you should definitely
know the security implications of the respective
usbcam
script you are going to use.
You must have the files
devices
and
drivers
in your
/proc/bus/usb
directory. Please check this.
If everything is OK, proceed with step 2. If not, check the following paragraph for hints.
Load your USB driver (e.g. OHCI or UHCI) and mount the USB device filesystem[1], i.e. e.g.
host:~#
modprobe
usb-uhci
host:~#
modprobe
usb-ohci
host:~#
mount
-t usbfs
usb
/proc/bus/usb
Modern distributions like Redhat 7.2 handle this automatically if you have your USB hardware enabled. Check your BIOS settings if lspci doesn't list any USB hardware.
Make hotplug recognise all USB cameras which your version of libgphoto2(3) supports.
Many of the modern[2]
(as of mid-2003) distributions,
you don't have to do much.
Just write the output of
/usr/lib/libgphoto2/print-usb-usermap[3]
to the /etc/hotplug/usb/
file:
usbcam
.usermap
host:~#
/usr/lib/libgphoto2/print-usb-usermap
>/etc/hotplug/usb/
usbcam
.usermap
That's it. Proceed with step 3.
However, if your distribution is an older one which
still wants you to modify
/etc/hotplug/usb.usermap
, or if modifying
/etc/hotplug/usb/
hasn't been enough, read on.
usbcam
.usermap
In the file /etc/hotplug/usb.usermap
remove all lines beginning with
“usbcam
”.
We are going to add new lines there and don't want to
have the old ones get in the way.
Add the output of
/usr/lib/libgphoto2/print-usb-usermap[3]
to the /etc/hotplug/usb.usermap
file:
host:~#
/usr/lib/libgphoto2/print-usb-usermap
>>/etc/hotplug/usb.usermap
Choose the right
/etc/hotplug/usb/
script for you.
usbcam
Example scripts are found in
packaging/linux-hotplug/
in the source tree and in the doc dir (usually
/usr/share/doc/gphoto2/
or something similar) under
linux-hotplug/
after installation.
Choose a script which fits your requirements best,
adapt it for your needs, and copy it to the file
/etc/hotplug/usb/
.
The script must be called
usbcam
/etc/hotplug/usb/
, not
usbcam
/etc/hotplug/usb/usbcam.user
or
something similar.
All the scripts shipped with gPhoto2 also have extensive commentary explaining their usage in more detail.
usbcam.group
camera
or a generic group
users
will do - and use that group in
usbcam.group
.
There is a specially marked line in
the script you have to change accordingly.
usbcam.console
usbcam.console
. This
changes the permissions so that the user owning
the console according to the
pam_console
module to access the camera. This works only if
you're logging in with
pam_console
,
i.e. e.g. using gdm on Redhat
Linux, and then only for the user logged in
last. It won't work on Debian GNU/Linux at all
(they claim security reasons, but I didn't
investigate further into that matter).
usbcam.user
usbcam.user
and change it
accordingly. There is a specially marked line in
the script you have to change.
usbcam.x11-app
usbcam.x11-app
and change it
accordingly. There are a few specially marked
lines in the script you have to change.
Make the script file executable:
host:~#
chmod
+x
/etc/hotplug/usb/
usbcam
Please do not forget that the script name is
/etc/hotplug/usb/
,
not
usbcam
/etc/hotplug/usb/usbcam.whatever
!
Test your setup.
Plug in the camera and switch it on. If you already did so, please unplug and/or switch off first. The kernel will now notice that your camera has been connected and, hopefully find no kernel driver for the device, and will then ask hotplug to do something about the new device file.
Hotplug will then look into
/etc/hotplug/usb/*.usermap
and find that
the
usbcam
script is to be called for
the newly attached device. Thus
/etc/hotplug/usb/usbcam
is executed,
hopefully setting the device permissions correctly.
Your /var/log/messages
syslog
file will contain some messages to that effect.
You will probably want to check whether the
respective device file has its permissions set up
correctly. Have a look at
/proc/bus/usb
with ls
. There
should be at least one device file (named something like
-lR
/proc/bus/usb
015
) with the
permissions set according to your wishes.
Run the id
command to find out
whether your process belongs to the proper groups. If
you have just added a user to a new group, only
processes started after a new login will actually belong
to the newly added group.
Run gphoto2(1) or any other libgphoto2(3) frontend and enjoy:
alice@host:~$
gphoto2
--list-ports
alice@host:~$
gphoto2
--auto-detect
alice@host:~$
gphoto2
--summary
alice@host:~$
gphoto2
--storage-info
alice@host:~$
gphoto2
--list-files
alice@host:~$
gphoto2
--get-all-files
The fact that we are using the name
“usbcam
” for
setting up permissions for gphoto2 has a reason. In fact,
the permission setup you're doing here has nothing to do
with gphoto2 specifically - any user space software
wanting to access your USB camera will be able to make use
of your camera only if the permissions are correctly set
up. So I (hun) chose the identifier and script name
“usbcam
” and
not “gphoto2cam” something similar.
This section only deals with FreeBSD 5 and over because older versions of FreeBSD do not have devfs, and thus do not handle dynamic devices at all (create static devices using MAKEDEV(8) there).
The editors would like to thank these FreeBSD users for their help (in no particular order): Tomasz Gucio, Georg Wagner, Michael Lyngbøl, Conan Webb, Bram Abbekerk, Roland Smith, and Guillermo A. Amaral (gamaral).
FreeBSD uses a dynamically created devices filesystem
(devfs).
In order to use the camera as non-root user, you need
to tell the devfs
framework what
permissions it is to use when it dynamically creates
these USB devices.
Follow the following steps as the
root
user to grant
write access for the group usb
to USB devices.
Create a group (using pw(8)
called something like
usb
. Add all
users as group members which are supposed to have
read/write access to attached USB devices. This
includes not only cameras, but also possibly scanners
and other devices.
For FreeBSD 7 and under add these lines to /etc/devfs.rules
:
[usb_devices=10] add path 'ugen*' mode 0660 group usb add path 'da*s*' mode 0660 group usb
The “ugen*” line will set the permissions for cameras using special camera protocols. The “da*s*” line will set up the same permissions for the slices of USB Mass Storage devices, such as a number of USB digicams.
For FreeBSD 8 and over add these lines to /etc/devfs.rules
:
[usb_devices=10] add path 'usb/*' mode 0660 group usb add path 'da*s*' mode 0660 group usb
The “usb/*” line will set the permissions for cameras using special camera protocols. The “da*s*” line will set up the same permissions for the slices of USB Mass Storage devices, such as a number of USB digicams.
Add a line to /etc/rc.conf
:
# Set the default devfs ruleset. devfs_system_ruleset="usb_devices"
Tomasz Gucio and Conan Webb report that user processes
need write access to the usb*
devices when they are supposed to write to
ugen*
. If you really need that,
add lines like the following to
/etc/devfs.conf
.
(FIXME: Can this be verified or invalidated?)
This is *not* required for FreeBSD 8.
perm usb0 0660 own usb0 root:usb perm usb1 0660 own usb1 root:usb
Activate your changes by running the following command (no reboot required):
host:~#
/etc/rc.d/devfs start
Your system should be all set up now. Now you can test it as your normal non-root user:
Make sure that you're actually member of the
usb
group. Check this by
running the id and, if the group
membership is not show, login anew.
Now connect your camera, and you'll get a line like
ugen1: Canon Inc. Canon Digital Camera, rev 1.10/0.01, addr 2
and the permissions to the device files should look something like this on FreeBSD 7 and under:
alice@host:~$
ls -l /dev/ugen*
crw-rw---- 1 root usb 242, 16 Apr 8 15:55 /dev/ugen1 crw-rw---- 1 root usb 242, 17 Apr 8 15:55 /dev/ugen1.1 crw-rw---- 1 root usb 242, 18 Apr 8 15:55 /dev/ugen1.2 crw-rw---- 1 root usb 242, 19 Apr 8 15:55 /dev/ugen1.3alice@host:~$
on FreeBSD 8 and over they should look something like this:
alice@host:~$
ls -l /dev/usb/
crw-rw---- 1 root usb 242, 16 Apr 8 15:55 /dev/usb/0.1.0 crw-rw---- 1 root usb 242, 17 Apr 8 15:55 /dev/usb/0.1.1 crw-rw---- 1 root usb 242, 18 Apr 8 15:55 /dev/usb/1.1.0 crw-rw---- 1 root usb 242, 19 Apr 8 15:55 /dev/usb/1.1.1alice@host:~$
FIXME for the FreeBSD instructions:
FIXME: This chapter still is to be written. If you know
about USB on these systems and/or are willing to contribute
text or hints, please contact the developers at
[ gphoto minus devel at lists dot sourceforge dot net ]
.
[1] The filesystem is called usbdevfs
in 2.2 and older 2.4 kernels.
[2] FIXME: how can you determine whether a specific system is "modern" in this sense? If you know how, please tell us.
[3]
In older versions of gphoto2 (gphoto2 2.0, gphoto2
2.1.0, and the unreleased developer versions in between and shortly
after 2.1.0), the functionality of
print-usb-usermap
was contained in the command
gphoto2
.
--print-usb-usermap