Python USB API for Canon digital cameras

Homepage:http://packages.python.org/canon-remote/
Author:Kiril Zyapkov <kiril.zyapkov@gmail.com>
Copyright:2012 Kiril Zyapkov
Version:0.0.1dev
Last updated:January 31, 2012

About this project

canon-remote is a USB library for Canon digital cameras in Python with pyusb, speaking the so-called normal mode. It originally started as a Python port of gphoto2‘s Canon library for a PowerShot G3. Only the subset necessary for this model was ported, but it should be usable with other models from that era (not without hacking) and will almost surely not work on much newer cameras, not without serious hacking. The project was created because gphoto2 lacks support for certain remote capture features, namely locking the autofocus and setting the autofocus mode to macro.

The latest project documentation can be found at the project homepage. Or you can build it from source.

The source is hosted at bitbucket.

You can contact me at kiril.zyapkov@gmail.com.

License

canon-remote is licensed under GPLv3.

Disclaimer

Canon is a registered trademark of Canon Inc. This project is an unofficial implementation of their closed USB camera protocol. I am not affiliated with Canon Inc. No information or code from them was used for this work. The protocol was reverse-engineered by the guys behind gphoto2, thanks guys!

Warning

Use this at your own risk. I haven’t damaged my camera with it yet, but it’s not impossible.

Installation

canon-remote depends only on pyusb version 1.0 or later. It was only tested with libusb-1.0 and Python 2.7 on a 64bit linux box. It will not work on any older Python versions and might work on Python 3.x with the 2to3 tool.

Installation should work fine via easy_install or pip:

$ pip install canon-remote

or the plain old:

$ python setup.py install

once you get the source.

Usage

You need to have permissions to talk to your camera. Chances are you already have gphoto2 installed which has the necessary udev rules in place, your user belongs to the right group, etc. If not, go make gphoto2 work and come back. Trying to use this as root would be pretty stupid.

To start playing with the driver, open up your favorite python terminal:

>>> from canon import camera
>>> cam = camera.find() # look for a G3, pass idProduct for other models
>>> cam
<Canon PowerShot G3 v1.0.2.0>

The camera object has a bunch of properties, some of which are writable:

>>> cam.firmware_version, cam.owner, cam.model
('1.0.2.0', 'adsf', 'Canon PowerShot G3')
>>> cam.owner = 'me, not asdf'
>>> cam.owner
'me, not asdf'

Setting the owner attribute caused a command to be sent to the camera. To get an idea what’s going on, look at the log:

>>> import logging
>>> l = logging.getLogger('canon')
>>> l.addHandler(logging.StreamHandler())
>>> l.setLevel(logging.INFO)
>>> cam.owner = 'Kiril'
--> SetOwnerCmd (0x5, 0x12, 0x201), #5
control_write (rt: 0x40, req: 0x4, wValue: 0x10) 0x56 bytes
bulk_read got 64 (0x40) b in 0.002964 sec
bulk_read got 20 (0x14) b in 0.001549 sec
<-- SetOwnerCmd #5 status: 0x0
--> IdentifyCameraCmd (0x1, 0x12, 0x201), #10
control_write (rt: 0x40, req: 0x4, wValue: 0x10) 0x50 bytes
bulk_read got 128 (0x80) b in 0.003996 sec
<-- IdentifyCameraCmd #10 status: 0x0
bulk_read got 28 (0x1c) b in 0.001196 sec

So setting owner caused a SetOwnerCmd to be executed, followed by an IdentifyCameraCmd. To admire a real time dump of all USB traffic, set the log level to DEBUG:

>>> cam.identify() # a slightly fancier logging format here ...
1327981738.91656 INFO   commands.py:239   --> IdentifyCameraCmd (0x1, 0x12, 0x201), #12
1327981738.91735 INFO   protocol.py:256   control_write (rt: 0x40, req: 0x4, wValue: 0x10) 0x50 bytes
1327981738.91797 DEBUG  protocol.py:257
0000  10 00 00 00 01 02 00 00  00 00 00 00 00 00 00 00   ;...;;.. ........
0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0040  02 00 00 00 01 00 00 12  10 00 00 00 0c 00 12 00   ;...;..; ;...;.;.
1327981738.92518 INFO   protocol.py:277   bulk_read got 128 (0x80) b in 0.003977 sec
1327981738.92605 DEBUG  protocol.py:278
0000  5c 00 00 00 01 03 00 00  00 00 00 00 00 00 00 00   \...;;.. ........
0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
0040  02 00 00 00 01 00 00 22  5c 00 00 00 0c 00 12 00   ;...;.." \...;.;.
0050  00 00 00 00 01 06 15 83  00 02 00 01 43 61 6e 6f   ....;;;; .;.;Cano
0060  6e 20 50 6f 77 65 72 53  68 6f 74 20 47 33 00 00   n PowerS hot G3..
0070  00 00 00 00 00 00 00 00  00 00 00 00 4b 69 72 69   ........ ....Kiri
1327981738.92663 INFO   commands.py:339   <-- IdentifyCameraCmd #12 status: 0x0
1327981738.92818 INFO   protocol.py:277   bulk_read got 28 (0x1c) b in 0.001210 sec
1327981738.92868 DEBUG  protocol.py:278
0000  6c 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   l....... ........
0010  00 00 00 00 00 00 00 00  00 00 00 00               ........ ....
('Canon PowerShot G3', 'Kiril', '1.0.2.0')

And so much for reliably implemented features.

The cam object above has two more interesting attributes:

storage
which exposes functions for accessing the camera filesystem, and
capture
which allows taking pictures.

Not much of those has been implemented, tested or documented yet.

Development

This is what I did to setup the environemnt canon-remote was developed in. I am sure there are other approaches, but this may be helpful for anyone willing to give it a shot.

Checkout gphoto2. It’s a bundle of software packages, the easiest way to get everything you need is to use the gphoto-suite “umbrella package”:

$ svn co https://svn.sourceforge.net/svnroot/gphoto/trunk/gphoto-suite gphoto-suite

Or, you could only get the source of libgphoto2 and look at libgphoto2/camlibs/canon/.

A way to sniff and analyze USB traffic is a must. I am using the original Remote Capture from Canon on Windows XP within a virtualbox machine. See this on how to enable USB support in a virtualbox guest. Wireshark runs on the host sniffing USB traffic. I wrote a small script to parse commands from stored pcap files using pcapy.

Indices and tables

Table Of Contents

This Page