Using Nikon Coolpix USB Camera in Linux

Kernel configuration

There are two types of USB digital cameras. Some are recognized as SCSI disk devices when connected, and can be mounted as an external disk:
 mount /dev/sda1 /mnt

while others are only accessible by direct communication over the USB bus. For these you need software that sends USB commands directly to the device. I used gphoto with a Nikon Coolpix 880 in SuSE linux version 8.0 running a 2.6.1 kernel.

Before starting, make sure your kernel is configured for USB 2.0, hotplug, and VFAT:
Alternatively, if using modules, make sure the corresponding modules are present and load them:
  modprobe usb-uhci
  modprobe usb-ohci
  mount -t usbfs usb /proc/bus/usb

Installing Gphoto

Download libgphoto2 and gphoto2 from and untar them:
   tar -xzvf libgphoto2-2.1.4.tar.gz
   cd libgphoto2-2.1.4
This software wouldn't compile on my system without editing the source code. Edit camlibs/aox/library.c and move the declaration of int header_len to the top of the function. In other words, change this
  int  header_len = snprintf(header, 127, 
to this:
 int header_len;
   /* And now create a ppm file, with our own header */
   header_len = snprintf(header, 127, 
Edit /camlibs/aox/aox.c and move declarations to the top of the function in aox_init and aox_get_picture_size the same way.

Compile and install it.
  make install   

Compile and install gphoto2.
  tar -xzvf gphoto2-2.1.4.tar.gz
  cd gphoto2-2.1.4
  make install  

Next, to avoid getting errors like the following:
 ./gphoto2: undefined symbol: gp_camera_set_timeout_funcs 

get rid of the old libraries if they're present and run ldconfig:
  cd /usr/lib
  mkdir oldlibgphoto
  mv libgphoto* oldlibgphoto/   
Edit /etc/ , add the line
and type ldconfig (warning: don't type this command without arguments in BSD).

Edit /etc/syslog.conf if necessary and make sure it shows all log entries
   *.*             /dev/xconsole   
and restart syslog
   /etc/rc.d/syslog restart   
and make the xconsole window really big. You will need it.

Connecting your camera

Make sure your camera is supported
gphoto2 --list-cameras   

Plug in camera and turn it on. Make sure the camera display's LCD screen doesn't say "error" as mine frequently does.

Messages like this will show up in your logs. This is normal.
kernel: hub 3-0:1.0: new USB device on port 1, assigned address 5
/etc/hotplug/usb.agent[30463]: Bad USB agent invocation
/etc/hotplug/usb.agent[30470]: lsmod: QM_MODULES: Function not implemented

Check to make sure linux was able to connect to the camera by typing lsusb (as root). It should give a complete listing with no errors.
Bus 003 Device 004: ID 04b0:0103 Nikon Corp. Coolpix 880
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass       255 Vendor Specific Subclass
  bDeviceProtocol       255 Vendor Specific Protocol
  bMaxPacketSize0         8
  idVendor           0x04b0 Nikon Corp.
  idProduct          0x0103 Coolpix 880
  bcdDevice            1.00
  iManufacturer           1 Nikon
  iProduct                2 Nikon Digital Camera E880
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               none
        wMaxPacketSize         64
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               none
        wMaxPacketSize         64
        bInterval               0
  Language IDs: (length=4)
     0409 English(US)
Then make sure gphoto can detect it:
gphoto2 --auto-detect
Model                          Port                                            
Nikon CoolPix 880              usb:          

This only needs to be done once, as it saves the result in a config file.

Try to find files on the camera
gphoto2 --shell
gphoto2: {...n/gphoto/gphoto2-2.1.4} /> ls

*** Error ***              
Too many retries failed.
*** Error (-1: 'Unspecified error') ***

gphoto2 --camera "Nikon CoolPix 880" --port usb: --list-files
*** Error (-35: 'Error writing to the port') ***   
You may get a slew of error messages on xconsole:
kernel: usbfs: USBDEVFS_CONTROL failed cmd usbmodules 
dev 5 rqt 128 rq 6 len 18 ret -32
kernel: usb 3-1: bulk timeout on ep3in 
(message repeated dozens of times)

On SuSE-Linux, the culprit was /etc/hotplug/usb.agent. This file assumes you are using modules. Get rid of this file.
mv usb.agent usb.agent.bak 

Change permissions so normal users can connect

Next run the program print-usb-usermap to get the parameters for your camera:
  cd gphoto/libgphoto2-2.1.4
  ./packaging/linux-hotplug/.libs/print-usb-usermap > \
  cp /etc/hotplug/usb/usb.usermap /etc/hotplug/
cat /etc/hotplug/usb/usb.usermap
# Nikon CoolPix 880
usbcam  0x0003  0x04b0  0x0103  0x0000  ... (etc)

Edit usb.usermap and change the first line from root to your username

Copy it to /etc/hotplug/ and rename it to usbcam:
  cd gphoto/libgphoto2-2.1.4/packaging/linux-hotplug# 
  chmod a+x usbcam.user 
  cp usbcam.user /etc/hotplug/usbcam
  cp usbcam.user /etc/hotplug/usb/usbcam 

Then, change the permissions on the USB bus so ordinary mortals can use it.
  chmod a+rwx /proc/bus/usb
  chmod a+rwx /proc/bus/usb/*
  chmod a+rwx /proc/bus/usb/*/*

Turn the camera off and on, or temporarily unplug it from the USB port. Now regular users should be able to copy files from the camera.

Using gphoto2

Gphoto2 can also control the camera:
gphoto2 --capture-image 
triggers the camera to take a picture remotely.

Gphoto2 acts more like ftp than a shell. Copy files by typing 'get'.
carbon:/etc/hotplug#  gphoto2  --list-files
There are no files in folder '/'.                                              
There are no files in folder '/DCIM'.
There are 49 files in folder '/DCIM/100NIKON':
#1     DSCN0663.JPG               rd   604 KB image/jpeg
#49    DSCN0711.TIF               rd  9327 KB image/tiff

gphoto2 --shell
get      (gets all files in current directory)

gphoto2 -P  = get all files
gphoto2 --list-files 

gphoto2 -p 47-49  

This number corresponds to the number printed when you type gphoto2 --list-files

After a while, if the file is large, it will invariably crash on the next file with an error:
Downloading 'DSCN0706.TIF' from folder '/DCIM/100NIKON'...
*** Error (-34: 'Error reading from the port') 
***       -   |  94.0%        3s

At this point, the USB channel was screwed up and it was necessary to turn the camera off and on in order to continue. This means the camera has to be turned off and on after every big file. Small files such as JPEGs don't seem to have this problem. For whatever reason, after this happened only root could copy files.

Another problem is that, if the file already exists, gphoto downloads the entire file before asking whether to overwrite the file on your disk. This can make things very slow.

This is obviously lots of trouble compared to Windoze, but at least it works, sort of.