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 |
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.
canon-remote is licensed under GPLv3.
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.
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.
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.
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.