libptp

Back in the early 2000s I created a popular library that was used to communicate with PTP devices (mainly digital cameras at that time). The original code that I wrote was for the gphoto2 application, namely it was a part of libgphoto2 and licensed under LGPL. Later on, I decided to continue development and released it as standalone library licensed under GPL. As it was completely rewritten along the way, I released it as libptp2 and included a companion app, ptpcam, meant to interact with cameras. As the PTP specification, although containing USB implementation details, was in principle transport layer independent, I designed the library in a way that it could work on any transport layer with any byte ordering which required some hefty macro magic at that time (and probably added a completely unnecessary level of complexity… eh… youth sins). The code was later used in libmpt, both via libptp2 and gphoto2, a library that implements Media Transfer Protocol.

What follows is slightly modified README, from the project:

libptp2 and ptpcam

libptp2 (c)2001-2016 Mariusz Woloszyn
ptpcam (c)2001-2016 Mariusz Woloszyn

About This Software

You may find new versions of this software at: http://emsi.me/libptp

The ./src folder contains the following code:

  • ptp.c: the main libptp2 code
  • ptp.h: libptp2 header files
  • ptp-pack.c: this file is included into ptp.c (internal code)
  • ptpcam.h: ptpcam header file
  • ptpcam.c: the software to manipulate PTP cameras; it does things that you can’t do with gphoto2

The libptp2 library is no longer under active development, but is considered to be functional and quite stable. It was written to be used with gphoto2, but can be easily used with any other software.

Requirements

Currently, this package requires libusb to build ptpcam. The libptp2 library itself is transport layer independent and does not require libusb; however, no other transport layer has been tested due to lack of PTP non-USB devices.

You can obtain libusb at http://libusb.sf.net/

BE AWARE THAT libusb-0.1.10 contained bugs that might affect your camera! Use a newer version or libusb-0.1.8 instead.

If you want to build this library (for test purposes) on a box without libusb, pass the --disable-ptpcam option to the configure script.

A PTP camera seems to be required also to take full advantage of this package.

What is libptp2?

libptp2 is a library used to communicate with PTP devices like still imaging cameras. At the current stage, you may use the ptpcam tool bundled with libptp2 to perform some basic operations like downloading photos or setting camera properties.

For other operations and GUI, you might consider using libgphoto2 (which contains a forked version of libptp2 code), gphoto2, and gtkam; see http://www.gphoto.org.

Supported Cameras

The list of PTP cameras is constantly growing. Most (if not all) USB still cameras designed after 2002 are PTP compliant. Below is the list of vendors implementing PTP in their cameras:

  • Kodak
  • HP
  • Nikon
  • Canon
  • Panasonic
  • Olympus
  • Konika
  • Minolta
  • Fuji
  • Ricoh
  • Sony

Note that for some HP, Nikon, Canon, Sony, and possibly other cameras, you have to switch them to PTP mode as in most cases the camera is dual mode: PTP and USB Mass Storage, or PTP and native. For some cameras, it even changes the Product ID number, so don’t panic, just switch the mode. Don’t ask me how to do it. Refer to the camera documentation.

Please note that if your camera supports PTP, it does NOT mean that it is capable of performing all PTP operations (like triggering capture, uploading files, or tweaking properties). Sony cameras are a good example of poor PTP implementation where the only thing you can do is download files.

Quick Start

First of all, you need kernel USB support. Please refer to your OS documentation for more info!

For Linux users, you need “Preliminary USB device filesystem” and “USB Host Controller” (the one for your hardware: EHCI, OHCI, or UHCI) support in your kernel. CAUTION: there was a bug in Linux Kernel 2.4.18 UHCI driver, so make sure you use a more recent kernel!

If you have kernel support, make sure that your usbdevfs is mounted under /proc/bus/usb. In my case, the fstab entry looks like this:

usb     /proc/bus/usb   usbdevfs        defaults,user 0 0

(NO, the entry in fstab isn’t enough, you have to type: mount /proc/bus/usb).

If you want to run ptpcam as a regular user, read this: http://gphoto.sourceforge.net/doc/manual/permissions-usb.html
although I suggest performing all tests as root unless you’re security paranoid.

If you have a PTP camera connected to your computer, it should be detected by invoking ptpcam --list-devices.
In my case, the output looks like this:

root@emsi(chroot):~# ptpcam --list-devices
Listing devices...
bus/dev vendorID/prodID device model
002/035 0x040A/0x0400   Kodak mc3
002/036 0x040A/0x0500   DX3500 Digital Camera
001/027 0x040A/0x0160   DC4800 Zoom Digital Camera

If you get something like this:

emsi@emsi(chroot):~> ptpcam --list-devices
Listing devices...
bus/dev vendorID/prodID device model
ERROR: Could not open session!
Try to reset the camera.

it means that you did not read carefully what I wrote above about running ptpcam as a regular user or your camera has stalled (needs reset).

If you need more debug information, try --verbose or --verbose=2, thus increasing the verbose level.

What if you get “Found no PTP devices”? If you’re sure that your camera is a PTP camera, please check your OS USB config. In case of Linux, make sure that you have usbdevfs mounted under /proc/bus/usb. If so, read the output of cat /proc/bus/usb/devices and check if your camera is listed there.

It might be that your camera is not in PTP mode. To verify, issue:

cat /proc/bus/usb/devices | grep "Cls=06"

If you find something like this:

I:  If#= 0 Alt= 0 #EPs= 3 Cls=06(still) Sub=01 Prot=01 Driver=(none)
                          ^^^^^^^^^^^^^

that means that your camera is in PTP mode and should be detected.
If there is no interface of Class 6, refer to camera documentation to find how to switch it into PTP mode.

You may also try to use the --force option while listing cameras or talking to them, but don’t use it unless you really know what you are doing!!! --force forces ptpcam to talk to non-PTP devices [which makes sense only in case of PTP devices with interface class other than 6 (PTP), like Kodak DC240 with PTP firmware]. BE AWARE that talking PTPish to non-PTP devices may cause harmful damage!!!

What Next?

I guess that you’d like to download images or tweak camera properties? 😉

Use ptpcam --get-all-files to download all images from your camera. By default, all images are copied to the local folder, and filename and creation time are preserved. By default, the download operation skips a file if it finds one with the same name in the local folder. This enables you to do quick-sync downloading only the newly captured files. Of course, you can request to overwrite existing files by passing --overwrite on the command line.

You may also download a specific file using --get-file=HANDLE, providing the object handle as a parameter (you can find it with --list-files).

If ptpcam detects more than one camera, you need to pass --bus=BUS-NUMBER and/or --dev=DEV-NUMBER arguments; otherwise, ptpcam tries to talk to the first detected camera. If you specify only bus or dev number, ptpcam talks to the first matching camera.

To list all available camera properties, use ptpcam --list-properties.
Unfortunately, if you have bought a high-end camera or a very expensive PTP camera, it DOES NOT mean that it supports setting any properties. The problem is that manufacturers do not specify in documentation what properties or operations are supported by the given camera. In most cases, you never know until you buy the camera. [I’ll try to provide a list of supported camera properties and operations on libptp.sf.net]

Let’s say that you get something like this:

root@emsi(chroot):~# ptpcam --list-properties
Listing properties...
Querying: DX3500 Digital Camera
0x5001 : Battery Level

It means that your camera (in this case DX3500 Digital Camera) supports only one property, which is “Battery Level” (property number 0x5001). Not much, but you still can try to list its value:

root@emsi(chroot):~# ptpcam --show-property=5001
Camera: DX3500 Digital Camera
Property 'Battery Level'
Current value is 100
Factory default value is 100
The property is read only, enumerated. Allowed values are:
0
10
100

As you can see, the --show-property argument does not require 0x; that’s for your convenience. 😉

The output of this command is quite verbose. It tells you about Current value, Factory default value, and the property type. The property type may vary among different cameras! In this camera, ‘Battery Level’ is read-only and enumerated. Allowed values are 0, 10, and 100, which (more or less) means: 0 – low battery level (may shut down immediately), 10 – medium battery level, 100 – full battery level. However, for a different camera, this property may be defined as a range of 1 to 100 with a step of 1. That’s just an example.

Now let’s look at the list of properties of another camera:

root@emsi(chroot):~# ptpcam --list-properties
Listing properties...
Querying: DC4800 Zoom Digital Camera
0x5001 : Battery Level
0x5003 : Image Size
0x5004 : Compression Setting
0x5005 : White Balance
0x5006 : RGB Gain
0x5007 : F-Number
0x5008 : Focal Length
0x5009 : Focus Distance
0x500a : Focus Mode
0x500b : Exposure Metering Mode
0x500c : Flash Mode
0x500d : Exposure Time
0x500e : Exposure Program Mode
0x500f : Exposure Index (film speed ISO)
0x5010 : Exposure Bias Compensation
0x5011 : Date Time
0x5013 : Still Capture Mode
0x5015 : Sharpness
0x5016 : Digital Zoom
0x5017 : Effect Mode
0x5018 : Burst Number
0x501c : Focus Metering Mode
0xd001 : EK Color Temperature
0xd002 : EK Date Time Stamp Format
0xd003 : EK Beep Mode
0xd004 : EK Video Out
0xd005 : EK Power Saving
0xd006 : EK UI Language

All properties of numbers starting with 0x50 are standard PTP properties, although for many of them, the type (enumerated or range) and value meaning are NOT specified by the PTP standard and may vary among different cameras!

The properties starting with 0xd0 are PTP extensions (in this case, EK means Eastman Kodak extension) and in most cases are not known to the public at all. Probably you will have to reverse-engineer their meaning (I’m eager to receive feedback from you in such a case! ;).

Setting Property Values

For example, if you’d like to change the ‘Image Size’ property, you have to do that in two steps. First, display the property using the --show-property switch. Determine whether the property is settable, what is the type of value (a number or string), and which values are supported!

Keep in mind that some properties are settable only in certain camera states or modes. Also, the valid values may vary depending on the current camera state!

OK. Let’s get back to our example. To display the property ‘Image Size’, which number is 0x5003, you have to type:

root@emsi(chroot):~# ptpcam --show-property=5003
Camera: DC4800 Zoom Digital Camera
Property 'Image Size'
Data type is 0xffff
Current value is "2160x1440"
Factory default value is "2160x1440"
The property is settable, enumerated. Allowed values are:
"2160x1440"
"1800x1200"
"1536x1024"
"1080x720"

As you can see, this camera supports four different image sizes. The property value is a string (values are printed within quotation marks).
To change the ‘Image Size’ property, pass --val=VALUE option to ptpcam while still specifying the property with --set-property=PROPERTY_NUMBER.
Note that only certain values are allowed.

In our example, let it look like this:

root@emsi(chroot):~# ptpcam --set-property=5003 --val=1080x720
Camera: DC4800 Zoom Digital Camera
Property 'Image Size'
Data type is 0xffff
Current value is "2160x1440"
Factory default value is "2160x1440"
The property is settable, enumerated. Allowed values are:
"2160x1440"
"1800x1200"
"1536x1024"
"1080x720"
Setting property value to '1080x720'

If everything goes OK, no error is displayed. You may verify, of course, if the property value was set properly.
If you get something like this:

PTP: Invalid Device Prop Value

it indicates that the property value was not set due to invalid values.

Keep in mind that in most cases, changing one property may cause another property to change! That happens especially in any Automated modes!!!

FIXME: The device should report that another property was changed by issuing a DevicePropChanged event! We may catch that and report it to the user.

Common Problems

Sometimes it might happen that the device claims to support a given property but does not respond to --show-property request. In most cases, it’s because of improper PTP implementation on the camera side.

Sometimes the list of supported properties might vary while changing camera mode.

Moreover, a given property may not have any meaning in a certain camera state. For example, setting or getting ‘Focus Distance’ property may not be allowed in automated camera mode! In such a case, try to switch the camera to manual mode.

For example, my Kodak DC4800 fails over --show-property=5006 (which is “RGB Gain”) if RGB Gain is not set. It looks like this:

root@emsi(chroot):~# ptpcam --show-property=5006
Camera: DC4800 Zoom Digital Camera
Property 'RGB Gain'
ERROR: Could not get device property description!
Try to reset the camera.

In such a case, you need to issue a --reset request to the camera:

root@emsi(chroot):~# ptpcam --reset
Resetting input pipe!
Device status OK

It’s a good practice to verify whether the reset went OK by issuing --list-devices. Sometimes one or two more resets may be needed to properly reset the camera.

Standard PTP Properties

Below, I am providing a short list of properties and their meaning values according to PTP specification.

[The document continues with detailed descriptions of standard PTP properties, which I’ll omit for brevity]

Camera Abilities

A couple of random camera abilities:

0.048332 PTP/library.c(2): Device info:
0.048347 PTP/library.c(2): Manufacturer: Nikon Corporation
0.048359 PTP/library.c(2):   model: E2500
0.048370 PTP/library.c(2):   device version: E2500v1.0
0.048380 PTP/library.c(2): Vendor extension description: Nikon PTP Extensions
0.048391 PTP/library.c(2): Supported operations:
0.048402 PTP/library.c(2):   0x1001
0.048413 PTP/library.c(2):   0x1002
0.048424 PTP/library.c(2):   0x1003
0.048435 PTP/library.c(2):   0x1004
0.048446 PTP/library.c(2):   0x1005
0.048457 PTP/library.c(2):   0x1006
0.048468 PTP/library.c(2):   0x1007
0.048479 PTP/library.c(2):   0x1008
0.048490 PTP/library.c(2):   0x1009
0.048500 PTP/library.c(2):   0x100a
0.048511 PTP/library.c(2):   0x100b
0.048522 PTP/library.c(2):   0x101b


0.309772 PTP/library.c(2): Device info:
0.309976 PTP/library.c(2): Manufacturer: Canon Inc.
0.310211 PTP/library.c(2):   model: Canon DIGITAL IXUS 400
0.310427 PTP/library.c(2):   device version:
0.310634 PTP/library.c(2): Vendor extension description: (null)
0.310861 PTP/library.c(2): Supported operations:
0.311066 PTP/library.c(2):   0x1001
0.311260 PTP/library.c(2):   0x1002
0.311455 PTP/library.c(2):   0x1003
0.311650 PTP/library.c(2):   0x1004
0.311844 PTP/library.c(2):   0x1005
0.312039 PTP/library.c(2):   0x1006
0.312233 PTP/library.c(2):   0x1007
0.312476 PTP/library.c(2):   0x1008
0.312674 PTP/library.c(2):   0x1009
0.312869 PTP/library.c(2):   0x100a
0.313064 PTP/library.c(2):   0x100b
0.313259 PTP/library.c(2):   0x100c
0.313457 PTP/library.c(2):   0x100d
0.313651 PTP/library.c(2):   0x100e
0.313846 PTP/library.c(2):   0x100f
0.314039 PTP/library.c(2):   0x1012
0.314233 PTP/library.c(2):   0x1014
0.321675 PTP/library.c(2):   0x1015
0.322120 PTP/library.c(2):   0x1016
0.322321 PTP/library.c(2):   0x101b
0.322518 PTP/library.c(2):   0x9001
0.322713 PTP/library.c(2):   0x9002
0.322909 PTP/library.c(2):   0x9003
0.323103 PTP/library.c(2):   0x9006
0.323299 PTP/library.c(2):   0x9008
0.323493 PTP/library.c(2):   0x9009
0.323689 PTP/library.c(2):   0x900a
0.323883 PTP/library.c(2):   0x900b
0.324079 PTP/library.c(2):   0x900c
0.324273 PTP/library.c(2):   0x900d
0.324583 PTP/library.c(2):   0x900e
0.324789 PTP/library.c(2):   0x900f
0.324985 PTP/library.c(2):   0x9010
0.325181 PTP/library.c(2):   0x9011
0.325377 PTP/library.c(2):   0x9012
0.325573 PTP/library.c(2):   0x9013
0.325767 PTP/library.c(2):   0x9014
0.325966 PTP/library.c(2):   0x9015
0.326162 PTP/library.c(2):   0x9018
0.326357 PTP/library.c(2):   0x9019
0.326554 PTP/library.c(2):   0x901a
0.326750 PTP/library.c(2):   0x901b
0.326945 PTP/library.c(2):   0x901c
0.327142 PTP/library.c(2):   0x901d
0.327337 PTP/library.c(2):   0x901e
0.327533 PTP/library.c(2):   0x901f
0.327729 PTP/library.c(2):   0x9020
0.327925 PTP/library.c(2):   0x9021
0.555111 PTP2/library.c(2): Events Supported:
0.555118 PTP2/library.c(2):   0x4001
0.555125 PTP2/library.c(2):   0x4002
0.555132 PTP2/library.c(2):   0x4003
0.555138 PTP2/library.c(2):   0x4004
0.555145 PTP2/library.c(2):   0x4005
0.555152 PTP2/library.c(2):   0x4006
0.555159 PTP2/library.c(2):   0x4008
0.555165 PTP2/library.c(2):   0x400a
0.555172 PTP2/library.c(2):   0x400c
0.555179 PTP2/library.c(2):   0x400d
0.555185 PTP2/library.c(2):   0xc001
0.555192 PTP2/library.c(2):   0xc005
0.555199 PTP2/library.c(2):   0xc006
0.555206 PTP2/library.c(2):   0xc007
0.555212 PTP2/library.c(2):   0xc008
0.555219 PTP2/library.c(2):   0xc009
0.555226 PTP2/library.c(2):   0xc00a
0.555233 PTP2/library.c(2):   0xc00b
0.555239 PTP2/library.c(2):   0xc00c
0.555246 PTP2/library.c(2):   0xc00d
0.555253 PTP2/library.c(2): Device Properties Supported:
0.555260 PTP2/library.c(2):   0xd001
0.555267 PTP2/library.c(2):   0xd002
0.555273 PTP2/library.c(2):   0xd003
0.555280 PTP2/library.c(2):   0xd02c
0.555287 PTP2/library.c(2):   0xd02d
0.555294 PTP2/library.c(2):   0xd02e
0.555300 PTP2/library.c(2):   0xd02f
0.555307 PTP2/library.c(2):   0xd030
0.555314 PTP2/library.c(2):   0xd031
0.555320 PTP2/library.c(2):   0xd032
0.555327 PTP2/library.c(2):   0xd033
0.555334 PTP2/library.c(2):   0xd034
0.555341 PTP2/library.c(2):   0xd045
0.555347 PTP2/library.c(2):   0xd046
0.555354 PTP2/library.c(2):   0xd047
0.555361 PTP2/library.c(2):   0xd048
0.555368 PTP2/library.c(2):   0xd049

0.509050 PTP/library.c(2): Device info:
0.509067 PTP/library.c(2): Manufacturer: Canon Inc.
0.509072 PTP/library.c(2):   model: Canon DIGITAL IXUS II
0.509077 PTP/library.c(2):   device version: 
0.509082 PTP/library.c(2): Vendor extension description: (null)
0.509091 PTP/library.c(2): Supported operations:
0.509096 PTP/library.c(2):   0x1001
0.509101 PTP/library.c(2):   0x1002
0.509106 PTP/library.c(2):   0x1003
0.509110 PTP/library.c(2):   0x1004
0.509114 PTP/library.c(2):   0x1005
0.509119 PTP/library.c(2):   0x1006
0.509142 PTP/library.c(2):   0x1007
0.509147 PTP/library.c(2):   0x1008
0.509152 PTP/library.c(2):   0x1009
0.509156 PTP/library.c(2):   0x100a
0.509160 PTP/library.c(2):   0x100b
0.509165 PTP/library.c(2):   0x100c
0.509169 PTP/library.c(2):   0x100d
0.509173 PTP/library.c(2):   0x100e
0.509178 PTP/library.c(2):   0x100f
0.509182 PTP/library.c(2):   0x1012
0.509186 PTP/library.c(2):   0x1014
0.509191 PTP/library.c(2):   0x1015
0.509195 PTP/library.c(2):   0x1016
0.509199 PTP/library.c(2):   0x101b
0.509203 PTP/library.c(2):   0x9001
0.509208 PTP/library.c(2):   0x9002
0.509212 PTP/library.c(2):   0x9003
0.509216 PTP/library.c(2):   0x9006
0.509221 PTP/library.c(2):   0x9008
0.509225 PTP/library.c(2):   0x9009
0.509229 PTP/library.c(2):   0x900a
0.509234 PTP/library.c(2):   0x900b
0.509238 PTP/library.c(2):   0x900c
0.509242 PTP/library.c(2):   0x900d
0.509247 PTP/library.c(2):   0x900e
0.509251 PTP/library.c(2):   0x900f
0.509255 PTP/library.c(2):   0x9010
0.509259 PTP/library.c(2):   0x9011
0.509264 PTP/library.c(2):   0x9012
0.509268 PTP/library.c(2):   0x9013
0.509272 PTP/library.c(2):   0x9014
0.509277 PTP/library.c(2):   0x9015
0.509281 PTP/library.c(2):   0x9018
0.509285 PTP/library.c(2):   0x9019
0.509290 PTP/library.c(2):   0x901a
0.509294 PTP/library.c(2):   0x901b
0.509298 PTP/library.c(2):   0x901c
0.509303 PTP/library.c(2):   0x901d
0.509307 PTP/library.c(2):   0x901e
0.509311 PTP/library.c(2):   0x901f
0.509316 PTP/library.c(2):   0x9020
0.509320 PTP/library.c(2):   0x9021