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

============================================
======   Canon PowerShot Series       ======
====  Transfer Protocol Specifications =====
============================================

* 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 S20.

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.

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

 Wolfgang G. Reissnegger, Werner Almesberger, Philippe Marzouk, Mikael
 Nystrm, Edouard Lafargue.


* 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:

   Update get_directory description to match what was discovered in USB.
   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.





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





============================================
==           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.


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).

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  one/two seconds     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.


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
  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.


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)
                03      used when uploading
                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> 		00 No error, acknowledged
                01 Not acknowledged
 		FF retransmit last sequence
                else other values not known


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 (except the one with type 03) have the following structure:

00 02 00 00  xx 00 00 xx  xx xx 00 00  ...
             |        |   |  |         |
             |        |   |  |         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 first four bytes  of the message payload  <fffb> seem to depend on
the message type. The following combinations have been sighted:

<mtype> <dir> <fffb>        Operation

01      12    14 f7 8a 00   Identify camera request
01      22    14 f7 8a 00   Identify camera response
01      11    6a 08 79 04   Download image request
01      11    aa 06 79 04   Download "thumbnail" request (see below)
01      21    6a 08 79 04   Image data
01      21    aa 06 79 04   "Thumbnail" data
03      11                  Upload file
03      12    78 f3 64 01   Get Date
04      12    08 d3 9d 00   Set date
05      12    fc d2 9d 00   Change Owner name
09      11    d8 f7 8a 00   Disk info request
09      21    d8 f7 8a 00   Disk info response
0a      11    dc f7 8a 00   Get disk(s) request
0a      21    dc f7 8a 00   Get disk(s) response
0a      12    70 f6 8a 00   Power Supply Status
0a      22    70 f6 8a 00   Power Supply Status response
0b      11    94 f6 8a 00   List without date request
0b      21    94 f6 8a 00   List without date response
0b      11    a8 f6 8a 00   List with date request
0b      21    a8 f6 8a 00   List with date response
0d      11    8c f4 7b 00   Delete image request
0d      21    8c f4 7b 00   Delete image response
0e      11    -- -- -- --   Set file attributes.

Important  note : it seems  that the  "fffb" part  can  be set to 0 in
every case, and  the commands  will still  work. The  exact meaning of
this part of the  packet is unknwown. It is  probably used as a unique
ID for each transaction and can be chosen at random each time.


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

The identify camera request has no data.

The identify camera response has the following structure:
00 00 00 00  00 02 00 00  00 00 00 01  <camera_name> 00  (more 00s)

On the S10, the response has the following structure:
00 00 00 00  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 (full packet): 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
----------------

Offsets in the payload:

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

Example (full packet):
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
----------------

The name (payload) can be 30 characters max.


Set Date
--------

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.


Get disk(s)
-----------

The get disk(s) request has no data.

The get disk response has the following structure:
00 00 00 00  <disk_name> 00

Disk name example: "C:"


Disk info
---------

Disk info requests have the following structure:
<root_name> 00

Disk info responses have the following structure:
00 00 00 00  xx xx xx xx  xx xx xx xx
             |            |
             |            Free space (in bytes)
             Total capacity (in bytes)

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


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

Note: It seems that directory listing as described  in the USB part is
more accurate,   when it comes  to  the meaning of   the  first byte (
"date/withtout date").

List requests have the following structure:
xx <directory_name> 00 00 00
|
00 if with date, 02 if without date

Directory name example: "C:\PWRSHOT", "D:", or "D:\.", but not
"D:\" (trailing slash), or "D:\.\FOO" (dot not allowed in path ?)

List responses have the following structure:
Failure:
00 00 00 00  01 00 00 00  00 00 00 00

Success:
00 00 00 00  xx 80 00 00  00 00 00 00  00 00 00 00
             |
             01 if last message, 00 if more
<directory_name> 00
<type> 00 <size> <date> <entry_name> 00
...
<type> 00 <size> <date> <entry_name> 00  (many 00s)

<type> is one byte containing the file attributes:
File attributes:
     bit0 (0x01) (1=delete protected, 0=NOT delete protected)
     bit4 (0x10) (1=directory contains item but not recursived entered)
                 (NOT used with the attrib command)
     bit5 (0x20) (1=NOT downloaded, 0=downloaded)
                 (must be manually switched)
     bit7 (0x80) (1=recurively entered directory)
                 (NOT used with the attrib command)


<size> is the size in bytes. Directory size is always 0.

Entry name example: "AUT_1201.JPG" or "MISC"

The date is a four bytes Unix-style date. The list without date responses
also contains the four data bytes, but sets them to zero.

Note: it's unclear if the list with/without date commands differ in any
other way than the inclusion of the date.

If the directory is so large that additional messages are needed, they
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 and Data
-----------------

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

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

All lengths are measured in bytes.

The camera only sends the 10813 first bytes from the image for the thumbnail
download request. However it is not a valid thumbnail image, the first part
is the Exif header, the second part is the thumbnail itself between a FF D8
and a FF D9, the remaining is the beginning of the picture.


The camera always sends 8 messages then 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 eight packet sent. These error values
are not yet known.

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 'A' If the response to step 1 was 'A',
      Control_transfer_read requesttype=0x4 value=0x4 length=0x50
      Throw away the data and we are finished with the initialization [1].

3 'C' If the response to step 1 was 'C', take the packet from step 2, change
      the byte at offset 0 to 0x10, move the last 0x10 bytes to position 0x40 and
      Control_transfer_write requesttype=0x40 value=0x11 length=0x50

4. PC sign should now appear on the LCD. Not all cameras have PC signs though.

5. We should now read a total of 0x44 bytes from bulk_in, but some cameras are
   picky at this stage and we must first read 0x40 bytes and then 0x4 bytes
   (the symptoms if not doing this right is that camera initialization only works
   every second time).
   Newer Canon USB cameras return 0x54 0x78 0x00 0x00 ('Tx\0\0') under some
   cicumstances [2] as the last four bytes in either of these two reads.
   If we get that from the first read we should not try to read the next 0x4 bytes.
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                                       ....               

[1] Many cameras fail the first camera command after this (the command response
    is returned without the first 0x40 bytes). It seems Canon got the same
    problem and worked around it in the Windows driver instead of fixing the
    firmware. The workaround is to retry the first camera command (Identify
    camera is a suitable command) up to four times.

[2] It seems this was due to an error in the init sequence described in earlier
    versions of this document. When done like the Windows driver does it, we
    always get 00 00 00 00 back as the last four bytes of step 5.

================================================================================
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 : sequence 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
 - Sequence 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 | 0x01 "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
0x1B   0x12   0x201 | 0x06 0x00 0x00 0x00                                        0x54 | EOS (D30) lock keys
0x1C   0x12   0x201 | none                                                       0x54 | EOS (D30) unlock keys
0x1F   0x12   0x201 | none                                                      0x380 | Get camera photo abilities?
0x20   0x12   0x201 | none                                                       0x54 | Lock keys, turn off LCD

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 in bit 4:
          ((value & 0x20) == 0)  running from ac-adaptor
          ((value & 0x20) != 0)  running from battery

Note that the original document claimed for 0x57 that it contained
"a byte with powertype: 0x10=ac-adaptor, 0x30=battery", whereas a 
PowerShot G2 just toggles one bit.

****
** 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 (0x01) (1=delete protected, 0=NOT delete protected)
     bit4 (0x10) (1=directory contains item but not recursived entered)
                 (NOT used with the attrib command)
     bit5 (0x20) (1=NOT downloaded, 0=downloaded)
                 (must be manually switched)
     bit7 (0x80) (1=recurively entered directory)
                 (NOT used with the attrib command)

Example: 0x21	file is NOT downloaded but delete protected


****
** 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:
     bit0 (0x01) (1=delete protected, 0=NOT delete protected)
     bit4 (0x10) (1=directory contains item but not recursived entered)
                 (NOT used with the attrib command)
     bit5 (0x20) (1=NOT downloaded, 0=downloaded)
                 (must be manually switched)
     bit7 (0x80) (1=recurively entered directory)
                 (NOT used with the attrib command)

Example: 0x21	file is NOT downloaded but delete protected

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.

- filname is "D:\DCIM\100CANON\IMG_0002.JPG"  for example (file cannot
  be created in nonexisting 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.......   
