This is the gphoto's description of the Canon PowerShot serial/USB
protocol, s10sh is based on this document.

(read/print this document with a non-proportional font such as courier)

============================================
======   Canon Powershot Series       ======
====  Transfer Protocol Specifications =====
============================================

Timestamp: 2000-06-29

* About this document

The following  document is an overview  of the Canon  Powershot serial
and USB transfer protocols. It should be a  valid reference for models
ranging from Powershot A5  to S100.

No  information present  in this   document was  obtained from  Canon.
Everything is  the result of observations  and logical analysis. It is
by no means guaranteed to be accurate, nor even right. Nevertheless, a
lot of people have managed to communicate with their Powershot cameras
using these commands, so they cannot be completely wrong either !

An  implementation of  this communication protocol   was made for  the
GPhoto digital camera  software, available  at www.gphoto.org. Another
program  implements this protocol:   s10sh,  which is a   command-line
interface. Look for their records on freshmeat.net !

* Contributors:
 
 This document was written thanks to the efforts of:

 Wolfgang G. Reissnegger, Werner Almesberger, Philippe Marzouk, Mikael
 Nystrm, Edouard Lafargue, Salvatore Sanfilippo <antirez@linuxcare.com>


* Copyright :

  The Canon Protocol information. Copyright (c) 2000 by its respective
  authors (see the Contributors section).

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or (at
  your option) any later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the:

  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  USA.

* To Do :

  (send updates to Edouard.Lafargue@bigfoot.com or to the
  gphoto-devel mailing-list)

  - Serial:

   Describe the structure of the initial ID packet.
   Find out what the real meaning of the "fffb" command is.
   Describe error recovery protocol.
   Describe format of low batt condition.
   Find out the rest of the commands that were discovered in USB:
       - Make dir
       - Delete dir
       - Change attribute
       - etc.
   Describe File upload.
   Describe each command in detail.

  - USB:

   Describe the generic get_directory reply packet with the location of
   the error code offset.

  - General:

    Rewrite this document in XML (LinuxDoc).

* Changelog:

 09  May 2000:  first  version  with both   USB and serial   protocols
                described in the same document.

 28 June 2000:  Merged the changes from Salvatore.



=========================================================================

============================================
==    Background information on the       ==
===      Canon Powershot series          ===
============================================

  Here's  some  information about  the hardware   found  in  the canon
powershot series cameras, in case you are interested:

  - Processor: 8086-compatible chip ()
  - Running the datalight embedded DOS (www.datalight.com)
  - Canon had their own name, "DigitalEye" for the OS/camera environment.

 It is  possible to look into the  camera embedded  softare by listing
other drives than the default flash card:

   A:  -> Main camera application (to be confirmed)
   B:  -> Data, tables (to be confirmed)
   C:  ->
   D:  -> CF card one
   E:  -> On the powershot 70, probably CF card two (to be confirmed)


============================================
==           Serial  Protocol             ==
===           Specifications             ===
============================================


Introduction
============

  We have  chosen to describe  the Canon Serial Protocol as successive
layers. I used OSI-like names but the protocol is not really a network
protocol.

   a. Data link layer:
        Responsible for framing, escaping and checksuming messages

   b. Transport (packet) layer:
        Responsible for dividing messages into packets of known length.
        This layer also handles handshaking, retries, etc.

   c. Session (message) layer:
        Last layer, carrying whole messages, such as download requests,
        image data, and such information.

 Currently, all these layers   are documented, but we  still lack
 information on how to handle protocol retries, and errors in general.


Data link layer
=====================

The following figure illustrates the lower layers of the protocol
used by some Canon PowerShot cameras:

[ Upper layers ]    Example: payload "00 C0 01"
   | ^
   | |              00 C0 01
  <CRC>
   | |              00 C0 01 12 34  (fictious CRC)
  <Escaping>
   | |              00 7E E0 01 12 34
  <Framing>
   | |              C0 00 7E E0 01 12 34 C1
   v |
[ Wire format ]

The upper layers are described later in this file.

Note that even the checksum bytes must be escaped.


0) Serial timing
----------------

Initialization: PC sends sequences of "U"  bytes at 9600 bps until the
camera responds by sending  its ID. Each sequence has  a length of 2-8
bytes. The  interval to    wait  between sequences  is   0.9-1.04  sec
(measured for 8 bytes).

On the S-series (S10/S20), the interval  can be even shorter, like 0.4
sec, so initialization is faster.

When the camera sends its ID,  the computer can ask it  to change to a
higher speed. The speed can go up to 115200 bps.

Afterwards, a  four/five second command timeout should  be  set.  E.g.
retrieving a directory with 1200 files  takes several seconds. Opening
a large  capacity flash  card takes time  as well.  It looks like  4/5
seconds is the camera's own timeout for receiving commands.



1) Framing
----------

Each  message begins with the  byte C0 and ends  with the byte C1. The
length of a message  including the framing bytes  and any escape bytes
(see below) never exceeds 1024 bytes.


2) Escaping
-----------

The value 7E is used to XOR the following byte with the value 0x20. This
is used for the following three combinations:
  7E 5E -> 7E
  7E E0 -> C0
  7E E1 -> C1


3) CRC
------

The last two bytes of a message (without framing and escaping) contain
a  16-bit  "CCITT" CRC in little-endian  order.  The CRC is calculated
over  the entire message,  without framing  and escaping, and  without
including the  CRC bytes. The CRC   generator [1] is initialized  to a
length-dependent value.  The algorithim for the   initial value is not
known.  However,  a table  of  values emitted  by the  camera has been
compiled  and is  in crc.c:crc_init.   It is indexed  by the   length,
i.e. the number of bytes over which the CRC is taken.


[1] Assuming the use of
    http://www.cse.fau.edu/~sam/course/dc_htm/src_dir/crc_att.c,
    generator polynom 0102010 (octal), the initial value of "crc" is
    the CRC generator's initial value (in the original code always
    zero).



Transport layer
=====================

Communication   is done through  messages,   which  may be split  into
several fragments, which are then sent  as individual packets. Packets
are framed as described earlier in this file.


Packet level
------------

Each packet consists of the following two-byte header:

<sequence> <ptype>

There are two sequence numbers: the message sequence number <mseq> and
the fragment sequence   number <fseq>. They are  counted independently
and  start at  zero.  <mseq> is reset at   the beginning of a session,
while <fseq> is reset at the beginning of each message.

The following packet types are known:
  00    Message fragment
  02    Switch the camera off
  03    Speed message from computer
  04    EOT
  05    ACK
  06    Compatibility?

A packet with type  03 is sent once, early  in the initialization  for
the computer to ask the camera to switch to a higher speed.

Each  message ends with an  EOT packet, which  is then confirmed by an
ACK packet. If the camera   does not get the ACK   it resends the  EOT
several times.


EOT has the following format:
xx 04 xx 00 00 00
|     |
|     indication of the message length. Known values:
<mseq>          00      empty message (no fragments)
                01      short message (one fragment)
                ff      maximum length data packet, more to follow
                else    data packet, at end (observed values: 0f, 7f)

ACK has the following format:
xx 05 xx 00 00 00
|     |
|     error code
<mseq>

The ACK error code  is 00 to ACKnowledge  the packet, a packet with 01
ask to the camera to resend the first fragment of the last message, 02
ask to the camera  to resend the second  fragment and so on. the  code
0xFF retransmits  all  the packets  of   the last message.    The  ACK
sequence number is initally 0, then it is incremented for every _good_
ACK. If  you send an  ack with error code !=  0 you must NOT increment
the ACK  sequence.

A packet  with type 06  is sent once, as  the first packet coming from
the camera. It contains a length, just like a normal message fragment,
but the message structure is different.

An empty message can be used to test if the camera is still responding.
If yes, it will respond with an ACK. Example:
PC->CAM  xx 04 00 00 00 00
CAM->PC  xx 05 00 00 00 00


Message fragment level
----------------------

Message fragments have the following structure:

xx 00 xx xx ...
|     |  |  |
|     |  |  fragment data
|     |  data length, MSB
|     data length, LSB
<fseq>

The data length  is the length  (in  bytes) of the  fragment data that
follows  the length. Fragment data is  simply concatenated to form the
complete message.


Session (message) Layer
=======================

All messages sent to/from the camera have the following structure:

02 00 00 00  xx 00 00 xx  xx xx 00 00  xx xx xx xx  ...
             |        |   |  |         |            |
             |        |   |  |         Serial nb.   message payload
             |        |   |  message length, MSB
             |        |   message length, LSB
             |        direction code <dir>
             message type <mtype>

The message length is the length  of the entire message, including the
header shown above.

The serial number can be chosen at random (use the date for example) and will be
returned in the response of the camera.

List of known message types/directions:

<mtype><dir>   Operation
	     
01      11      Download file
01      12      Identify camera
03      11      Upload file (?)
03      12      Get Date
04      12      Set date
05      11      Make directory
05      12      Change Owner name
06      11      Remove directory
09      11      Disk info request
0a      11      Get flash device identification
0a      12      Power Supply Status
0b      11      List directory
0d      11      Delete file
0e      11      Set file attributes

	     
01      22      Identify camera response
01      21      File download data
03      22      Get Date response
09      21      Disk info response
0a      21      Get disk(s) response
0a      22      Power Supply Status response
0b      21      List without date response
0b      21      List with date response
0d      21      Delete image response


A  message with <mtype>  02 is  sent by the   camera to notify that it
isn't no longer if PC-transfer  mode (<-._> symbol), this happens when
the user switches the camera to some other mode.

The four first bytes of each response message is the error code of the
operation. Here's the list of known codes:

 0x00000000 : Success
 0x02000022 : No such file
 0x02000029 : File is protected
 0x02000040 : No such directory
 0x02000087 : No such disk
 0x02000086 : Path not found (?)

------------------------------------------
-  List Of commands
------------------------------------------

  Each command is described in the following format:

Command name
------------

  * Explanation of what the command does

  * Format of the request packet.

  * Format of the response packet with offsets to
    each part of the data. Offset zero is the first
    byte after the error code.

  * Example of request packet (with framing/escaping)
  * Example of response packet (after unescaping/without framing/CRC)


Identify camera
---------------

   * Asks the camera for some of its parameters: model, firmware, owner.

   * The identify camera request has no data.

   * The identify camera response has the following structure:

    - A5/A50 models :

     00 02 00 00  00 00 00 01  <camera_name> 00  (more 00s)

    - S10/S20 :

     00 04 00 00  00 00 00 01 and then:
      <firmware rev> (32 bit word) (offset: 0x08)
      <model name>   (C string)    (offset: 12 / 0x0c)
      <owner name>   (C string)    (offset: 44 / 0x2c)

    Firmware version: 04 03 02 01 is version 1.2.3.4
                      01 00 00 01 is version 1.0.0.1

   * Example of id camera request:
WRITE: (24 bytes)
00000000: C0 00 00 10 00 02 00 00 00 01 00 00 12 10 00 00 - ................
00000010: 00 14 F7 8A 00 AD 7A C1                         - ......z.

   * Example of id camera response, for a PowerShot S10
     with firmware 1.0.0.0
RECV: (98 bytes)
00000000: 00 00 5C 00 02 00 00 00 01 00 00 22 5C 00 00 00 - ..\........"\...
00000010: 14 F7 8A 00 00 00 00 00 00 04 00 00 00 00 00 01 - ................
00000020: 43 61 6E 6F 6E 20 50 6F 77 65 72 53 68 6F 74 20 - Canon PowerShot 
00000030: 53 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 - S10.............
00000040: 45 64 6F 75 61 72 64 20 4C 61 66 61 72 67 75 65 - Edouard Lafargue
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................
00000060: 9C EA                                           - ..


Get Power Status
----------------

   * This command show the current power status of the camera

   * The get power status command has no data.

   * The get power status response has the following structure:

     0x00 contains a byte with power status: 0x6=good, 0x4=bad
     0x03 contains a byte with powertype: 0x10=ac-adaptor, 0x30=battery

   * Example of get power status request:
WRITE: (24 bytes)
00000000: C0 00 00 10 00 02 00 00 00 0A 00 00 12 10 00 00 - ................
00000010: 00 70 F6 8A 00 7B 46 C1                         - .p...{F.

   * Example of get power status response:
RECV: (30 bytes)
00000000: 00 00 18 00 02 00 00 00 0A 00 00 22 18 00 00 00 - ..........."....
00000010: 70 F6 8A 00 00 00 00 00 06 00 00 30 B5 5A       - p..........0.Z



Change Owner Name
----------------

   * This  command sets the owner name  in the camera.  I  am not sure
this command is  supported in the  A-series, but both  the S10 and the
S20 support it.

   * The payload is a C string (null-terminated) of 30 characters max.

   * Response: the response contains the error code only.


Get Date
--------

   * This command returns the internal date of the camera. As powershots
     don't contain a timezone, the date is returned must not be converted
     to local time.

   * Payload: no data

   * Response format:
     Offsets:
        0x00 : Date, unix format, local time, little-endian

   * Example of request packet:
WRITE: (24 bytes)
00000000: C0 00 00 10 00 02 00 00 00 03 00 00 12 10 00 00 - ................
00000010: 00 78 F3 64 01 A7 77 C1                         - .x.d..w.

   * Example of response packet:
RECV: (38 bytes)
00000000: 00 00 20 00 02 00 00 00 03 00 00 22 20 00 00 00 - .. ........" ...
00000010: 78 F3 64 01 00 00 00 00 90 1B 5A 39 00 00 00 00 - x.d.......Z9....
00000020: 00 00 00 00 57 CC                               - ....W.


Set Date
--------

   * This command sets the date in the camera.

   * Request format:
The  payload  of this message  is 4  bytes, it  must  be the same unix
format  as in   the directory with    date  request, for  example  the
01/01/2000 is 80 43 6D 38.

   * Response format

   * Example of request packet:

   * Example of response packet:


Make directory
--------------

  * Creates a directory in the camera.

  * Request format:
The payload of this message is a null-terminated string containing the
name of the directory to create.

  * Response format:
The response packet only contains the error code:

  * Example of request packet:
[Canon PowerShot S10] D:> mkdir ED
WRITE: (30 bytes)
00000000: C0 00 00 16 00 02 00 00 00 05 00 00 11 16 00 00 - ................
00000010: 00 00 00 00 00 44 3A 5C 45 44 00 13 7F C1       - .....D:\ED....

  * Example of response packet:
RECV: (26 bytes)
00000000: 00 00 14 00 02 00 00 00 05 00 00 21 14 00 00 00 - ...........!....
00000010: 00 00 00 00 00 00 00 00 48 6E                   - ........Hn


Remove directory
----------------

   * Removes a directory in the camera.

   * Request format:
The payload of this message is a null-terminated string containing the
name of the directory to delete.

   * Response format:
The response packet only contains the error code:
   0x0 in case of success
   0x2000040 in case of error (no such directory)

   * Example of request packet:
WRITE: (31 bytes)
00000000: C0 00 00 16 00 02 00 00 00 06 00 00 11 16 00 00 - ................
00000010: 00 00 00 00 00 44 3A 5C 45 44 00 2B 7E 5E C1    - .....D:\ED.+.^.

   * Example of response packet:

     Returned packet after a successful directory deletion :
RECV: (26 bytes)
00000000: 00 00 14 00 02 00 00 00 06 00 00 21 14 00 00 00 - ...........!....
00000010: 00 00 00 00 00 00 00 00 69 F4                   - ........i.

      Returned packet after a rmdir of a non-existing dir:
RECV: (26 bytes)
00000000: 00 00 14 00 02 00 00 00 06 00 00 21 14 00 00 00 - ...........!....
00000010: 00 00 00 00 40 00 00 02 CC C1                   - ....@.....



Flash device identification
---------------------------

   * Returns the name of the flash drive where pictures are stored.

   * The flash device request has no arguments.

   * The flash device response has the following structure:
       0x0: C-string containing the disk name.

   * Example of request:
WRITE: (24 bytes)
00000000: C0 00 00 10 00 02 00 00 00 0A 00 00 11 10 00 00 - ................
00000010: 00 DC F7 8A 00 A9 FF C1                         - ........

   * Example of response:
RECV: (30 bytes)
00000000: 00 00 18 00 02 00 00 00 0A 00 00 21 18 00 00 00 - ...........!....
00000010: DC F7 8A 00 00 00 00 00 44 3A 00 00 49 5E       - ........D:..I^


Disk info
---------

    * Disk info returns the total capacity  and free space
      on the requested device.

    * Disk info requests have the following structure:
        0x0: C-String containing the name of the device ("D:\")

        Root name example: "C:\" (The trailing slash is required.)

    * Disk info responses have the following structure:
	0x0: 32bit integer representing total capacity
	0x4: 32bit integer representing free space

             xx xx xx xx  xx xx xx xx
             |            |
             |            Free space (in bytes)
             Total capacity (in bytes)

        Error code: 0x00000000 in case of success
                    0x02000087 in case of error (non-existing drive)

    * Request example:
WRITE: (28 bytes)
00000000: C0 00 00 14 00 02 00 00 00 09 00 00 11 14 00 00 - ................
00000010: 00 D8 F7 8A 00 44 3A 5C 00 74 B6 C1             - .....D:\.t..

    * Response example:

    Error: (diskinfo Z:)
RECV: (34 bytes)
00000000: 00 00 1C 00 02 00 00 00 09 00 00 21 1C 00 00 00 - ...........!....
00000010: D8 F7 8A 00 87 00 00 02 18 00 3C 19 94 2A 0E 00 - ..........<..*..
00000020: DD 4B                                           - .K

    Success: (diskinfo A:)
RECV: (34 bytes)
00000000: 00 00 1C 00 02 00 00 00 09 00 00 21 1C 00 00 00 - ...........!....
00000010: D8 F7 8A 00 00 00 00 00 80 E8 06 00 00 00 00 00 - ................
00000020: A5 C0                                           - ..



List (show directory contents)
------------------------------

   * This command lists directory contents for a specified directory.

   * Structure of request packets:

List requests have the following structure:
xx <directory_name> 00 00 00
|
recursion byte

The "recursion byte" can take the following values:

  0x00: non-recursive query
  0x01: One level of recursion
  0x02: Complete recursive directory listing ("ls -lR")


Directory  name example: "C:\PWRSHOT",  "D:", or "D:\.", but not "D:\"
(trailing  slash),  or "D:\.\FOO"   (dot  not allowed  in path  ?).  A
double-dot can be included in the path: "D:\DCIM\..".


   * Structure of response packets:

List  responses  have the following structure   (after  the error code
which is always at "0x0" in case of dir lists).

Failure:
         01 00 00 00  00 00 00 00
Success:
         xx 80 00 00
         00 00 00 00
         00 00 00 00
         <directory_name>
         <type> 00 <size> <date> <entry_name>
         ...
         <type> 00 <size> <date> <entry_name>
         <one entry with all bytes to zero>

   - <directory_name> and <entry_name> are C-strings (null-terminated)
   - <xx> is:  01 if the packet is the last message
               00 if more packets are to follow.
   - <type> is one byte containing the file attributes:
        File attributes:
             bit 0: 1= write protected, 0=NOT write protected
             bit 4: 1=directory contains item but not recursived entered
             bit 5: 1=NOT downloaded, 0=downloaded (must be manually switched)
             bit 7: 1=recurively entered directory
   - <size> is the size in bytes (4 bytes/little-endian).
            Directory size is always 0.
   - <date> is a four bytes Unix-style  date in little-endian format.


     * Example of a directory get sequence  on a S10:

[Canon PowerShot S10] D:> dir d:
WRITE: (30 bytes)
00000000: C0 00 00 16 00 02 00 00 00 0B 00 00 11 16 00 00 - ................
00000010: 00 A8 F6 8A 00 00 64 3A 00 00 00 65 4C C1       - ......d:...eL.
WRITE: (10 bytes)
00000000: C0 04 04 01 00 00 00 88 D6 C1                   - ..........
RECV: (8 bytes)
00000000: 04 05 00 00 00 00 77 C1                         - ......w.
RECV: (66 bytes)
00000000: 00 00 3C 00 02 00 00 00 0B 00 00 21 3C 00 00 00 - ..<........!<...
00000010: A8 F6 8A 00 00 00 00 00 01 80 00 00 00 00 00 00 - ................
00000020: 00 00 00 64 3A 00 10 00 00 00 00 00 C4 6A 42 39 - ...d:........jB9
00000030: 44 43 49 4D 00 00 00 00 00 00 00 00 00 00 00 00 - DCIM............
00000040: DC CA                                           - ..
RECV: (8 bytes)
00000000: 03 04 01 00 00 00 59 CA                         - ......Y.
WRITE: (10 bytes)
00000000: C0 03 05 00 00 00 00 A6 DD C1                   - ..........

-i--  DCIM          <DIR>        Sat Jun 10 18:20:20 2000
        1 files      0 bytes


On  S10/S20, if  the  directory   is  so  large that several   message
fragments are needed, the fragments are  transmitted the normal way as
and the sequence is terminated by an EOT  (usual way of transmitting a
multi-fragment message).

On the A5/A50 however, the following behaviour was described:

If the directory is so large  that additional messages are needed, the
following messages   have the following   structure:

 00 00 00 00 xx <entry>
             |
             1 if last message, 00 if more

The boundary between messages is always chosen such that the terminating
00 of an entry is the last byte in the earlier message.


Download file
-------------

   * This command gets a file from the camera. An option allows to get
  the thumbnail instead of the whole file.

   * Structure of request packets:

Download requests have the following structure:
xx 00 00 00  00 xx 00 00 <name>
 |               |
 |               Length of name (including terminating \0)
 0x00 for image
 0x01 for thumbnail

   * Structure of response packets:

Data messages have the following structure:
00 00 00 00  xx xx xx xx  xx xx xx xx  xx xx xx xx  xx 00 00 00 ...
             |            |            |            |           |
             |            |            |            |           data
             |            |            |            00 if more, 01 at end
             |            |            data size in this message
             |            current offset
             total length

You can check if the request generated an  error checking for the byte
at offset 0x16 (00 if  more, 01 at end)  since it is  set to 01 in the
first packet if the downloaded failed (this is just an hack since this
detection method will fail is the file is shorter than one fragment)

All lengths are measured in bytes/little-endian.

The camera always sends 8 messages then sends an  EOT and waits for an
ACK from the computer, if the computer has not received everything, it
sends an  ACK  with an  error value  asking  to retransmit one of  the
eighth packet sent. These error values are not yet known.

Note about thumbnails for S10/S20 models:

The camera only sends   the 10813 first bytes  of  the image for   the
thumbnail  download request.   However it  is  not a valid image:  the
camera response you get  just contains enough data  to parse  the EXIF
header and extract the  thumbnail.    The remaining bytes left   after
parsing are the beginning of the actual image and should be discarded.
In  order to get the  thumbnail, you will have to  look for values "FF
D8" and "FF D9" in the data , and  the thumbnail (valid jpeg image) is
between these  two values (including ffd8  and ffd9).  This is not the
prefered method as "ffd8" and "ffd9" can appear  anywhere in the data.
It is best to parse the header properly. Gphoto offers an EXIF parsing
API.


   * Example of request:
WRITE: (62 bytes)
00000000: C0 00 00 36 00 02 00 00 00 01 00 00 11 36 00 00 - ...6.........6..
00000010: 00 6A 08 79 04 01 00 00 00 00 1E 00 00 44 3A 5C - .j.y.........D:\
00000020: 64 63 69 6D 5C 31 31 38 63 61 6E 6F 6E 5C 69 6D - dcim\118canon\im
00000030: 67 5F 31 38 34 31 2E 6A 70 67 00 62 C4 C1       - g_1841.jpg.b..

   * Examples of answers:

    - Error for a get on a non-existing file:
RECV: (42 bytes)
00000000: 00 00 24 00 02 00 00 00 01 00 00 21 24 00 00 00 - ..$........!$...
00000010: 6A 08 79 04 22 00 00 02 00 00 00 00 00 00 00 00 - j.y."...........
00000020: 00 00 00 00 01 00 00 00 A4 A3                   - ..........

    - First bytes of the first fragment in case of success:
RECV: (1022 bytes)
00000000: 00 00 F8 03 02 00 00 00 01 00 00 21 24 1E 00 00 - ...........!$...
00000010: 6A 08 79 04 00 00 00 00 9B 1E 00 00 00 00 00 00 - j.y.............
00000020: 00 1E 00 00 00 00 00 00 FF D8 FF E1 1D FE 45 78 - ..............Ex
00000030: 69 66 00 00 49 49 2A 00 08 00 00 00 09 00 0F 01 - if..II*.........
00000040: 02 00 06 00 00 00 7A 00 00 00 10 01 02 00 14 00 - ......z.........
00000050: 00 00 80 00 00 00 12 01 03 00 01 00 00 00 01 00 - ................
00000060: 00 00 1A 01 05 00 01 00 00 00 94 00 00 00 1B 01 - ................
00000070: 05 00 01 00 00 00 9C 00 00 00 28 01 03 00 01 00 - ..........(.....
........: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. -



Upload file
-----------

   The serial upload protocol description is not done yet. These are just
 ideas on what it could be. Maybe it's right, maybe it's wrong.

   * This command sends a file to the camera.

   * Request structure:
xx 00 00 00  00 xx 00 00 <name>

Each data block has the following format:

00 00 00 02 XX XX XX XX - YY YY YY YY filename - datablock

   XX XX XX XX : offset within the file for this block
   YY YY YY YY : len2: length of this block
   filename : 0-terminated string
   datablock: the data itself.


Switch Camera off
-----------------

In order to  switch the  camera off, you   need to send the  following
characters (directly, without extra framing) :

     C0 00 02 55 2C C1
     C0 00 04 01 00 00 00 24 C6 C1


Low Battery warning
-------------------

If the camera batteries run  too low during a  transfer and the camera
needs to switch itself off, it will  send a special packet just before
going down. You can see how it is handled in psa50.c



===============================================
=
=   USB Interface
=
===============================================

Nota:
 When mentioning word, 32bit word little_endian is implied.

References to usb11.pdf (Chaper 9.3 page 199):
http://www.usb.org/developers/data/usbspec.zip (1.8Mb)

bmRequestType is 0xC0 during read and 0x40 during write.
bRequest is 0x4 if length of data is >1, 0x0c otherwise (length > 1 ? 0x04 : 0x0C)
wValue differs between operations.
wIndex is always 0x00
wLength is simply the length of data

In linux sending/reciving commands is using usb_control_msg (in usb.c).

 usb11.pdf name  |   usb.c name)
--------------------------------
  bmRequestType  | requesttype 
  bRequest       | request
  wValue         | value
  wIndex         | index
  wLength        | length

================================================================================
Init of camera:
================================================================================

1. Control_transfer_read requesttype=0xC0 value=0x55 length=1

Camera responds with following data (single char):
"A" = Camera was already active
"C" = Camera was woken up
"I" = Unknown (some kind of error)
"E" = Unknown (some kind of error)

2. Control_transfer_read requesttype=0xC0 value=0x1 length=0x58

The first 0x48 bytes can be trashed, save the last 0x10 byte and us it as
data in next step.
Example:
00000000   18 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   01 00 02 00 43 30 A9 04-00 08 00 00 FF FF FF FF   ....C0..........
00000050   00 FD 00 00 00 FD 00 00                           ........           

3. Control_transfer_write requesttype=0x40 value=0x11 length=0x10 data=[from step 2]

4. PC sign should now appear on the LCD

5. Receive 0x44 bytes from bulk_in and throw it away.
Example:
00000000   04 00 00 00 02 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   00 00 00 00                                       ....               

================================================================================
USB Commands
================================================================================

1. Structure of a command block

Example:

* Command block sent in general: (Example:Disk info request)
    0000000: 14 00 00 00 01 02 00 00-00 00 00 00 00 00 00 00 ................
    0000010: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
    0000020: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
    0000030: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
    0000040: 02 00 00 00 09 00 00 11-14 00 00 00 78 56 34 12 ............xV4.
    0000050: 44 3A 5C 00                                     D:\.

USB arguments:
   - value is always 0x10
   - length is TOTAL length (0x54 in example above)

* Generic format of block sent:

0000000: xx xx xx xx yy yy yy yy - 00 00 00 00 00 00 00 00
0000010: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0000020: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0000030: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0000040: 02 00 00 00 UU 00 00 VV - xx xx xx xx SS SS SS SS
0000050: ... (payload/arguments)

     xx xx xx xx : Length (word)
     yy yy yy yy : cmd3 (word)
     UU          : cmd1 (byte)
     VV          : cmd2 (byte)
     xx xx xx xx : Length (again)
     SS SS SS SS : serial number (word)

 - 'length' is the length of the block, excluding the first 0x40 bytes
   in block, and is never less than 0x10.
 - cmd1 and cmd2 are a single byte
 - cmd3 is a word
 - Serial number is a word, sent back in command reply.

2. Summary of available (known) commands:

cmd1 | cmd2 |  cmd3 | Argument(eg.)                                   Response Length |  Operation
-----------------------------------------------------------------------------------------------
0x01   0x11   0x202 | 0x00000000 0x00001400 "D:\DCIM\100CANON\IMG_0100.JPG" 0x00    L | Get picture 
0x01   0x11   0x202 | 0x00000001 0x00001400 "D:\DCIM\100CANON\IMG_0100.JPG" 0x00    L | Get thumbnail
0x01   0x12   0x201 | none                                                       0x9c | Identify camera request
0x03   0x12   0x201 | none							 0x60 | Get time
0x04   0x12   0x201 | 0x390873f0 0x00000000 0x00000000                           0x54 | Set time (0x390873f0) (UNIX-type)
0x05   0x11   0x201 | "D:\DCIM" 0x00 						 0x54 | Make directory
0x05   0x12   0x201 | "Donald Duck" 0x00                                         0x54 | Change owner
0x06   0x11   0x201 | "D:\DCIM" 0x00						 0x54 | Remove directory
0x09   0x11   0x201 | "D:\" 0x00                                                 0x5c | Disk info request
0x0A   0x11   0x202 | none                                                          L | Flash device identification
0x0A   0x12   0x201 | none                                                       0x58 | Power supply status
0x0b   0x11   0x202 | 0x1 "D:\DCIM" 0x00 0x00 0x00                                  L | Get directory (0x1 = max depth of recursion)
0x0d   0x11   0x201 | "D:\DCIM\100CANON" 0x00 "IMG_0002.JPG" 0x00                0x54 | Delete file
0x0E   0x11   0x201 | 0x00000021 "D:\DCIM\100CANON" 0x00 "IMG_0002.JPG" 0x00     0x54 | Set file attribute

L means that the program reads 0x40 from bulk in, checks for a word at
position 0x6 for the length (0xd1fcf in this case), and then reads the
rest in 0x1400 buffers. (long bulk in read)

00000000   00 00 00 00 02 03 CF 1F-0D 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................   

****
** Disk Info Request:
****

* Argument structure:

  Null-terminated string containing the name of the disk.

* Camera response block:

Data received via bulk in after a command block: (Disk info request)
0000000: 00 00 00 00 01 03 00 00 00 00 00 00 00 00 00 00 ................
0000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0000040: 02 00 00 00 09 00 00 21 1C 00 00 00 78 56 34 12 .......!....xV4.
0000050: 00 00 00 00 00 80 E8 03 00 A0 AF 03             ............

     First 0x40 bytes is throwable.
     0x54 contains a word with totalbytes on flash.
     0x58 contains a word with bytes free.

****
** Delete directory
****
Data received via bulk in after a command block: (Delete directory)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 06 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   00 00 00 00                                       ....               

****
** Make directory
****
Data received via bulk in after a command block: (Make directory)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 05 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   00 00 00 00                                       ....               


****
** Get time
****

Data received via bulk_in after a command block: (Get time)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 03 00 00 22-20 00 00 00 78 56 34 12   ......." ...xV4.
00000050   00 00 00 00 8D 1D 12 39-00 00 00 00 00 00 00 00   .......9........   

     First 0x40 bytes is throwable.
     0x54 contains a UNIX time

****
** Power supply status
****

Data received via bulk_in after a command block: (Power supply status)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0A 00 00 22-18 00 00 00 78 56 34 12   ......."....xV4.
00000050   00 00 00 00 06 00 00 10-                          ........           

     First 0x40 bytes is throwable.
     0x54 contains a byte with power status: 0x6=good, 0x4=bad
     0x57 contains a byte with powertype: 0x10=ac-adaptor, 0x30=battery

****
** Identify Camera request
****

Data received via bulk_in after a command block: (Identify camera request)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 01 00 00 22-5C 00 00 00 78 56 34 12   ......."\...xV4.
00000050   00 00 00 00 00 04 00 00-01 00 00 01 43 61 6E 6F   ............Cano
00000060   6E 20 50 6F 77 65 72 53-68 6F 74 20 53 32 30 00   n PowerShot S20.
00000070   00 00 00 00 00 00 00 00-00 00 00 00 44 6F 6E 61   ............Dona
00000080   6C 64 20 44 75 63 6B 00-00 00 00 00 00 00 00 00   ld Duck.........
00000090   00 00 00 00 00 00 00 00-00 00 00 00               ............       

    First 0x40 bytes is throwable (as usual)
    At 0x5c a string with camera type exist
    At 0x7c a string with owner name exist.
    0x58-0x5b is firmware version (04 03 02 01 is version 1.2.3.4; 01 00 00 01 is version 1.0.0.1)
    Data at 0x54-0x57 has unknown purpose.

****
** Flash device identification
****

Data received via a long_bulk_in_read: (Flash device identification)
00000000   44 3A 00 00                                       D:..  

****
** Set File Attribute
****

Data received via bulk_in after a command block: (Set file attribute)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0E 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   00 00 00 00                                       ....               

Data received via bulk_in after a command block: (Set file attribute) (file did not exist).
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0E 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   22 00 00 02                                       "...               


File attributes:
     bit0 (1= write protected, 0=NOT write protected)
     bit4 (1=directory contains item but not recursived entered)
          (NOT used with the attrib command)
     bit5 (1=NOT downloaded, 0=downloaded)
          (must be manually switched)
     bit7 (1=recurively entered directory)
          (NOT used with the attrib command)

Example: 0x21	file is NOT downloaded but deleteprotected


****
** Delete file
****

Data received via bulk_in after a command block: (Delete file) (file did not exist).
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0D 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   22 00 00 02                                       "...               

Data received via bulk_in after a command block: (Delete file) (file was protected)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0D 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   29 00 00 02                                       )...

Data received via bulk_in after a command block: (Delete file) (successful)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 0D 00 00 21-14 00 00 00 78 56 34 12   .......!....xV4.
00000050   00 00 00 00                                       ....               


****
** Change Owner
****

Data received via bulk_in after a command block: (Change owner) (no errorcodes)
00000000   00 00 00 00 01 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 05 00 00 22-14 00 00 00 78 56 34 12   ......."....xV4.
00000050   00 00 00 00                                       ....               

****
** Directory Listing
****

Errorcodes:
0x02000022  File not found
0x00000000  No errors
0x02000086  Path not found
0x02000029  File was protected

File attributes:
bit1 (1=deleteprotected, 0=NOT deleteprotected)
bit4 (1=directory contains item but not recursived entered) (NOT used with the attrib command)
bit5 (1=NOT downloaded, 0=downloaded)  (must be manually switched)
bit8 (1=recurively entered directory) (NOT used with the attrib command)

Example: 0x21	file is NOT downloaded but deleteprotected

Directory handling:
Thu May  4 00:11:40 2000   D:\DCIM\100CANON\IMG_0001.JPG    778435
Thu May  4 00:28:32 2000   D:\DCIM\100CANON\IMG_0002.JPG    44409
Thu May  4 00:28:32 2000   D:\DCIM\CANONMSC\100.CTG    2634
Thu May  4 00:28:32 2000   D:\DCIM\CANONMSC\D.CTG    383                        

Directory contents: "D:" (recurse =0x0)
00000000   80 00 00 00 00 00 00 00-00 00 44 3A 00 10 00 00   ..........D:....
00000010   00 00 00 C6 B5 10 39 44-43 49 4D 00 00 00 00 00   ......9DCIM.....
00000020   00 00 00 00 00 00 00                              .......

Directory contents: "D:" (recurse =0x1)
00000000   80 00 00 00 00 00 00 00-00 00 44 3A 00 80 00 00   ..........D:....
00000010   00 00 00 36 C0 10 39 2E-5C 44 43 49 4D 00 10 00   ...6..9.\DCIM...
00000020   00 00 00 00 36 C0 10 39-31 30 30 43 41 4E 4F 4E   ....6..9100CANON
00000030   00 10 00 00 00 00 00 CC-B5 10 39 43 41 4E 4F 4E   ..........9CANON
00000040   4D 53 43 00 80 00 00 00-00 00 00 00 00 00 2E 2E   MSC.............
00000050   00 00 00 00 00 00 00 00-00 00 00 00               ............

Directory contents: "D:" (recurse =0x2)
00000000   80 00 00 00 00 00 00 00-00 00 44 3A 00 80 00 00   ..........D:....
00000010   00 00 00 36 C0 10 39 2E-5C 44 43 49 4D 00 80 00   ...6..9.\DCIM...
00000020   00 00 00 00 3C C0 10 39-2E 5C 31 30 30 43 41 4E   ....<..9.\100CAN
00000030   4F 4E 00 20 00 C3 E0 0B-00 3C C0 10 39 49 4D 47   ON. .....<..9IMG
00000040   5F 30 30 30 31 2E 4A 50-47 00 20 00 79 AD 00 00   _0001.JPG. .y...
00000050   30 C4 10 39 49 4D 47 5F-30 30 30 32 2E 4A 50 47   0..9IMG_0002.JPG
00000060   00 80 00 00 00 00 00 00-00 00 00 2E 2E 00 80 00   ................
00000070   00 00 00 00 30 C4 10 39-2E 5C 43 41 4E 4F 4E 4D   ....0..9.\CANONM
00000080   53 43 00 20 00 4A 0A 00-00 30 C4 10 39 31 30 30   SC. .J...0..9100
00000090   2E 43 54 47 00 20 00 7F-01 00 00 30 C4 10 39 44   .CTG. ....0..9D
000000A0   2E 43 54 47 00 80 00 00-00 00 00 00 00 00 00 2E   .CTG............
000000B0   2E 00 80 00 00 00 00 00-00 00 00 00 2E 2E 00 00   ................
000000C0   00 00 00 00 00 00 00 00-00 00                     ..........         

Directory contents:
attribute 0x00 size date "name" 0x00
attribute is a byte describe little earlier in this document
 (0 in attribute, date, length and name  means end of direntry, ".." in name means "leave directory".
size is a word (filesize in byte)
time is a word (UNIX time)


****
** Upload (a little bit special):
****

Control_transfer_write
  requesttype=0x40
  value=0x10
  length=0x40
  data=0x00000000 0x0203 0x40+len1[explained later] [0x00 repeated 0x38]

Example:
00000000   00 00 00 00 03 02 7A 14-00 00 00 00 00 00 00 00   ......z.........
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

bulk_in_read [0x40 bytes]
Example:
00000000   00 00 00 00 03 03 00 00-00 00 00 00 00 00 00 00   ................
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................   

bulk_write [data below]

len1[explained later] 0x00 0x00 0x00000403 0x00000000 0x00000000
[0x00 repeated 0x30 times]
0x00000002 0x03 0x00 0x00 0x11 len1 0x00 0x00 serial   (this line looks very similar to "ordinary" commands)
0x00000002 offs len2 filename 0x00 datablock

bulk_in_read [0x5c bytes]

This is repeated until the whole file is transmitted:

- offs is a word that starts at 0 and increments with blocksize each time.

- len1 is the length of the "bulk_write_data" block above, minus 0x40 (the
  first length and padded  zeros is not counted as in all other commands).
  len1   is typically 0x143A using  a  standard  0x1400 (ms-windows) block
  using the filename below (29 chars), last block is shorter.

- len2 is length  of datablock (0x1400  is used  in ms-windows), last
  block is shorter

- serial is a random word that is returned as a reply.

- filename is "D:\DCIM\100CANON\IMG_0002.JPG"  for example (files cannot
  be created in non-existing directory.)

- datablock is the datablock itself (the fragment of the JPG file).

Example of beginning of a block (first one):
00000000   3A 14 00 00 03 04 00 00-00 00 00 00 00 00 00 00   :...............
00000010   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
00000040   02 00 00 00 03 00 00 11-3A 14 00 00 78 56 34 12   ........:...xV4.
00000050   02 00 00 00 00 00 00 00-00 14 00 00 44 3A 5C 44   ............D:\D
00000060   43 49 4D 5C 31 30 30 43-41 4E 4F 4E 5C 49 4D 47   CIM\100CANON\IMG
00000070   5F 30 30 30 32 2E 4A 50-47 00 FF D8 FF E1 17 FE   _0002.JPG.......
00000080   45 78 69 66 00 00 49 49-2A 00 08 00 00 00 09 00   Exif..II*.......
00000090   0F 01 02 00 06 00 00 00-7A 00 00 00 10 01 02 00   ........z.......   

 * ALL THIRD PARTY BRAND, PRODUCT AND SERVICE NAMES MENTIONED ARE
 * THE TRADEMARK OR REGISTERED TRADEMARK OF THEIR RESPECTIVE OWNERS
