Table of Contents
Notes
When mentioning word, 32bit word little-endian is implied.
References to usb11.pdf (Chapter 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/receiving commands is using usb_control_msg (in usb.c).
usb11.pdf name | usb.c name |
---|---|
bmRequestType | requesttype |
bRequest | request |
wValue | value |
wIndex | index |
wLength | size |
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; seen with a hotplug problem on Linux)
E Unknown (some kind of error)
Control_transfer_read requesttype=0xC0 value=0x1 length=0x58
The first 0x48 bytes can be trashed, save the last 0x10 bytes and use them 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 ........
The bytes 0x40-0x43 seem to vary from camera to camera: the S20 here has 01000200. These bytes might identify which version of the protocol is used. The following table summarizes our observations to date.
Table 3.1. Unknown contents of response packet
Models | 0x40 | 0x44 | 0x48 | 0x4C | 0x50 | 0x54 |
---|---|---|---|---|---|---|
G1, Pro90 IS, Digital IXUS | 00 05 07 00 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
S10, S20 | 01 00 02 00 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
G2, D30, D60, 300D, S110, A10, A20, S30, S300 | 01 00 05 03 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
300D | 01 00 05 83 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
G3, A60, A70, A75, A80, A300, A400, A510, S45, S50, S230, S400, SD200 | 01 06 15 83 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
S1 IS | 01 06 15 83 | 04 a9 30 85 | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
20D | 01 06 15 83 | 0x80000175 | 0x800 (2048) | 0x10000 (65536) | 0xfd00 (64768) | 0x10000 (65536) |
350D | 01 06 15 83 | 0x80000189 | 0x800 (2048) | 0x10000 (65536) | 0xfd00 (64768) | 0x10000 (65536) |
Optura 200 MC camcorder | 03 05 04 81 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
Optura 20, Optura 40 camcorders | 03 05 04 81 | USBid | 0x200 (512) | -1 | 0x200 (512) | 0xfd00 (64768) |
S200, S330, A30, A40, A200 | 03 05 15 81 | USBid | 0x800 (2048) | -1 | 0xfd00 (64768) | 0xfd00 (64768) |
In the older version of the protocol, the USB vendor and product ID are normally contained in bytes 0x44-0x47 of this packet: here 0x04A93043 for vendor 0x04a9, product 0x3043 identifies this as a PowerShot S20.
Unfortunately, the meaning of these bytes seems to have changed in the newer protocol; for an EOS 20D, we get 0x80000175, which is identical with bytes 0x56-0x59 of a response to the Get Photo Abilities request. This is interesting, because the same bytes wind up in each JPEG or CR2 file as a LONG value for tag 0x10 within the MakerNote. That may be a model identifier for the camera.
Even stranger, there seems to be a group of cameras (apparently using the older protocol) that all report 0x3085 as the product ID, which is correct for the PowerShot G5.
The bytes 0x48-0x57 also vary from camera to camera. I think they are 4-byte integers, and suspect that they specify maximum transfer sizes in some way.
If the response to step 1 was 'A',
Control_transfer_read requesttype=0x4 value=0x4 length=0x50. Example:
0000 10 00 00 00 00 00 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 00 08 00 00 ff ff ff ff 00 fd 00 00 00 fd 00 00 ................
This looks to me like the payload (here from an EOS D30) duplicates the last 16 bytes of the previous packet.
Throw away the data and we are finished with the initialization[2].
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
PC sign should now appear on the LCD. Not all cameras have PC signs though.
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 circumstances[3]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 ....
Read 16 (0x10) bytes from the interrupt endpoint. Some newer cameras (e.g. the PowerShot S50) return the bytes 8 at a time, so two reads may be needed. The code in bytes 0x44-0x47 is 0x20.
Example (EOS 300D):
0000 02 00 00 00 20 00 00 00-10 00 00 00 00 00 00 00 .... ...........
Note: The EOS 20D seems to return the 16 bytes (8 at a time) after the Power supply status command, rather than here.
[2] 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.
[3] It seems this was due to an error in the init sequence described in earlier versions of this document. When done as the Windows driver does it, we always get 00 00 00 00 back as the last four bytes of step 5.