This is the documentation of the USB SCSI communication between computer and Pentax camera. Although several requests had been made, there is no official documents from Pentax. This is a summary from understanding of current implementations and analysis of Pentax camera/firmware.
To control the Pentax camera, the camera has to be set to Mass Storage (MSC) mode, rather than PTP mode.
There are 2 kind of commands referenced in this document, one is the low level SCSI command
, another is the higher level Command
, which is consist of several low level SCSI commands
.
Pentax camera is controlled via SCSI Pass-through interface of USB Mass Storage. Vendor specific SCSI command
is used to communicate with Pentax camera.
SCSI command
contains 8
bytes in the following format:
[F0 TT X2 X3 X4 X5 X6 X7]
- The leading byte is the SCSI opcode, and always be
0xF0
, which means Vendor Specific. TT
is the type of thisSCSI command
, can be following values:
0x24: Send Command
0x26: Get Command Status
0x4F: Send Arguments
0x49: Read Result
X2, X3, X4, X5
have different meaning for differentTT
.X6, X7
are always zero.
The SCSI command
is limited to 8 bytes, a data buffer associated with the SCSI command
can be used to transfer more data to/from camera. The associated data buffer is used in this protocol for both data transfer direction.
Such as, Send Arguments SCSI command
will use the associated data buffer to send arguments to camera, and Read Result SCSI command
will use the associated data buffer to receive the result from camera.
For the reason, there are 2 kind of SCSI operation, scsi_write()
and scsi_read()
.
Most SCSI commands
will be called via scsi_write()
, as they are simply passing data to the camera, however, some will be called via scsi_read()
to receive data.
The high level Command
is more like a function, which has function name, arguments, and returned data. To achieve such task, several SCSI Commands
are used in the following way:
- Computer sends the arguments by
SCSI Command - 0x4F
first, if there is any; - Computer sends a command call by
SCSI Command - 0x24
; - Computer keep checking the status by
SCSI Command - 0x26
until the status is ok; - Computer receive the result by
SCSI Command - 0x49
, if needed.
The individual commands will be discussed later.
Each Command
can have arguments. If the command does have one or more arguments, the arguments will be send to camera separately, before sending the command.
This SCSI command
will not be sent if there is no any argument.
The TT
code for sending arguments is 0x4F
The SCSI command
format of sending arguments is:
[F0 4F X0 X1 Y0 Y1 00 00]
X0 X1
is a Little-Endian 16-bit integer,0xX1X0
, which isthe offset of the arguments
;Y0 Y1
is also a Little-Endian 16-bit integer,0xY1Y0
, which isthe size of the arguments
.
Both of the offset
and size
are in bytes, and should be aligned to 4 (32-bit).
The maximum number of arguments are limited to 8
, which is 32 bytes
, so X1
and Y1
are always be 0x00
.
To explain the concept of offset of the arguments
, we can imagine that there is an arguments buffer
on the camera side, and for each time we send an argument(s), we need to specify where we want to put our arguments in the arguments buffer
. The location is specified by the offset
. Camera will simply follow our instruction and save the argument in the buffer at the given offset
, and later the SCSI command - 0x24
will trigger the camera to load arguments list from this buffer.
So, for example, if we're going to send the first argument, the offset should be 0x00
. After the first argument sent, if we decide to send more arguments, we will need to call SCSI command - 0x4F
again. But as camera side didn't keep how many arguments we have sent, we need to specify the offset for those new arguments. This time, the offset should be 0x04
, as we have put our first argument in the buffer at offset 0x00
, and each argument should be 4 bytes(32-bit) aligned.
The reason Pentax is using offset
design to pass the arguments is that, on some old Pentax cameras, the buffer to receive SCSI command
associated data is very small (maybe just 4 bytes), so the arguments has to be passed in multiple times (such as one by one), so an offset
is necessary to tell the camera where the arguments in current SCSI command
should be put in the arguments buffer
.
It's important to check the byte-order of the camera. Older Pentax cameras have Big-Endian system, K-3 or later Pentax cameras have a Little-Endian system. The arguments data buffer should be constructed in the same way of camera's.
The TT
code for sending command is 0x24
.
The SCSI command
format of sending command is:
[F0 24 C0 C1 X0 X1 00 00]
C0
isCommand Group
,C1
is the command number in the group. The combination ofC0 C1
defines theCommand
.X0 X1
is a Little-Endian 16-bit integer,0xX1X0
, which is the byte length of the previously sent arguments, and should be aligned to 4 (32-bit). For example, if one argument was sent previously, theX0 X1
should be04 00
. As the arguments number is quite small,X1
will always be zero.- As discovered in K-S1 firmware,
X0 X1
are not used anymore.
After the SCSI command - 0x24
has been sent, we need to know what's the status of the execution. Is it still running? or completed successfully? or got any error? This SCSI command
is to retrieve the current command execution status, and the length of the result may also be returned.
TT
code is 0x26
. SCSI command
format is:
[F0 26 00 00 00 00 00 00]
As the status data will be returned from camera, this SCSI command
should be sent by scsi_read()
, and the status data will be return via associated data buffer.
The status data which camera returned is an 8
bytes array, in following format.
[L0 L1 L2 L3 00 00 S0 S1]
L0 L1 L2 L3
is a Little-Endian 32-bit integer,0xL3L2L1L0
, which is the length of the returned data.S0
andS1
are the status code.- (S0 == 0x01): Ready to read the result;
- (S1 == 0x01): Completed Successfully;
- (S1 == 0x81): Error: Command not available
- (S1 == 0x82): Error: Command Rejected
- (S1 == 0x83): Error: Illegal Parameter
To retrieve the result data of the command we sent earlier, this SCSI command
will be used, the TT
code is 0x49
. The SCSI command
will be send via scsi_read()
, and the associated buffer will be the result data. The SCSI command
format is:
[F0 49 X0 X1 L0 L1 00 00]
X0 X1
is a Little-Endian 16-bit integer,0xX1X0
, which is the offset of the result data, and should be aligned to 4 (32-bit).L0 L1
is a Little-Endian 16-bit integer,0xL1L0
, which is the size of the result data we want to read, and should be aligned to 4 (32-bit).
Normally, we'll just leave X0 X1
to zero, and L0 L1
to the length of the whole content to be read.
When parsing the result data buffer, it's very important to check the byte-order of the camera, the returned result should be as same as camera's internal byte-order. Older Pentax cameras have Big-Endian system, K-3 or later Pentax cameras have a Little-Endian system, we need to parse the data in the same way of the camera.
This is the list of Commands
have been discovered by now. The Command
will be defined as:
[C0 C1] Command Name (arg0, arg1, ...)
- The arguments,
(arg0, arg1, ...)
, will be sent viaSCSI Command - 0x4F - Send Arguments
. - If the arguments is
()
, that means there is no arguments for thecommand
, so noSCSI Command - 0x4F
will be called. C0
is theCommand Group
, andC1
is thecommand number in the group
, the combination of[C0 C1]
will be sent viaSCSI Command - 0x24 - Send Command
.
on_off
: 1: Connect, 0: Disconnect
This command will return first 16
or 28
bytes of the whole status data.
The camera id consists of two 32-bit integers, the format is:
[A0 A1 A2 A3 B0 B1 B2 B3]
It will be returned in the same byte order of the camera, so for Little-Endian system, such as K-3, the id is {0xA3A2A1A0, 0xB3B2B1B0}
.
This command is used for old camera only.
This command will return the full status data, normally several hundreds bytes.
The status data includes camera settings, the range of some settings, battery status, etc. Although many fields are shared in different models, the offset of each fields may be different, and there might be new fields added in later model. It's very important to check whether the status data is correct or not for debugging or supporting new Pentax cameras.
The status data is actually a memory dump of the camera, so it's very important to check the byte order of the camera, the data should be parsed as the same way of camera.
mode
: 1: Before our commands; 2: After our commands
This command returns 4 bytes in following format:
[X0 X1 X2 X3]
For Big-Endian cameras the firmware version is X0.X1.X2.X3 for Little-Endian cameras it is X3.X2.X1.X0
This command requests the image buffer status, and the result should be read by 0x49
, Read Result, command. The result is 8 bytes data in following format:
[X0 X1 X2 X3 Y0 Y1 Y2 Y2]
X0 X1 X2 X3
is an 32-bit integer, for each bit is corresponding a buffer status, 0
is empty, 1
is not empty.
For old camera, there is only 3 arguments:
(buffer_number, buffer_type, buffer_resolution)
buffer_type
typedef enum {
PSLR_BUF_PEF,
PSLR_BUF_DNG,
PSLR_BUF_JPEG_MAX,
PSLR_BUF_JPEG_MAX_M1,
PSLR_BUF_JPEG_MAX_M2,
PSLR_BUF_JPEG_MAX_M3,
PSLR_BUF_PREVIEW = 8,
PSLR_BUF_THUMBNAIL = 9 // 7 works also
} pslr_buffer_type;
This command deletes the specified buffer. Indexing starts from 0
.
The downloadable content of the selected image buffer are stored in chunks. The maximum number of chucks is four. Information about the chucks are stored in segments information blocks. The maximum number of blocks is ten.
This command reads information about the currently selected segment information block. This command returns 16 bytes representing 4 32-bit integers: a
, b
, addr
, length
. b
is the type of the block.
b==1
is the first information block. In this caseaddr
, andlength
are 0.b==4
defines the position in out output file where we should write the next chunk.length
stores this byte position,addr
is always 0 in this case.b==3
gives us the position of the next chuck of the image in the internal buffer of the camera.addr
defines the position,length
is the number of bytes we can read.b==2
is the last information block. In this caseaddr
, andlength
are 0.
For instance a buffer stored in four chunks are represented the following segment information blocks: b1, b4, b3, b4, b3, b4, b3, b4, b3, b2
. The length
field of the b4
blocks are always equals to the sum of the length
fields of the b3
blocks before.
This command changes to the next segment information block. It is possible to cycle through the blocks.
This command seems to dump given memory area to a buffer, so it can be retrieved later.
This is a scsi_read()
command, and the attached buffer will be the downloaded data.
press_status
: 1: Half pressed, 2: Full pressed.
on_off
: 1: Connect, 0: Disconnect
on_off
: 1: Start, 0: Stop
typedef enum {
PSLR_EXPOSURE_MODE_P = 0 ,
PSLR_EXPOSURE_MODE_GREEN = 1,
// PSLR_EXPOSURE_MODE_HYP = 2,
// PSLR_EXPOSURE_MODE_AUTO_PICT = 1,
// PSLR_EXPOSURE_MODE_GREEN = 3, maybe 1 is AUTO_PICT
PSLR_EXPOSURE_MODE_TV = 4,
PSLR_EXPOSURE_MODE_AV = 5,
// PSLR_EXPOSURE_MODE_TV_SHIFT = 6, //?
// PSLR_EXPOSURE_MODE_AV_SHIFT = 7, //?
PSLR_EXPOSURE_MODE_M = 8,
PSLR_EXPOSURE_MODE_B = 9,
PSLR_EXPOSURE_MODE_AV_OFFAUTO = 10,
PSLR_EXPOSURE_MODE_M_OFFAUTO = 11,
PSLR_EXPOSURE_MODE_B_OFFAUTO = 12,
PSLR_EXPOSURE_MODE_TAV = 13, // ?
PSLR_EXPOSURE_MODE_SV = 15,
PSLR_EXPOSURE_MODE_X = 16, // ?
PSLR_EXPOSURE_MODE_MAX = 17
} pslr_exposure_mode_t;
typedef enum {
PSLR_AE_METERING_MULTI,
PSLR_AE_METERING_CENTER,
PSLR_AE_METERING_SPOT,
PSLR_AE_METERING_MAX
} pslr_ae_metering_t;
typedef enum {
PSLR_FLASH_MODE_MANUAL = 0,
PSLR_FLASH_MODE_MANUAL_REDEYE = 1,
PSLR_FLASH_MODE_SLOW = 2,
PSLR_FLASH_MODE_SLOW_REDEYE = 3,
PSLR_FLASH_MODE_TRAILING_CURTAIN = 4,
PSLR_FLASH_MODE_AUTO = 5,
PSLR_FLASH_MODE_AUTO_REDEYE = 6,
// 7 not used
PSLR_FLASH_MODE_WIRELESS = 8,
PSLR_FLASH_MODE_MAX = 9
} pslr_flash_mode_t;
typedef enum {
PSLR_AF_MODE_MF,
PSLR_AF_MODE_AF_S,
PSLR_AF_MODE_AF_C,
PSLR_AF_MODE_AF_A,
PSLR_AF_MODE_MAX
} pslr_af_mode_t;
typedef enum {
PSLR_AF_POINT_SEL_AUTO_5,
PSLR_AF_POINT_SEL_SELECT,
PSLR_AF_POINT_SEL_SPOT,
PSLR_AF_POINT_SEL_AUTO_11, // maybe not for all cameras
PSLR_AF_POINT_SEL_MAX
} pslr_af_point_sel_t;
#define PSLR_AF_POINT_TOP_LEFT 0x1
#define PSLR_AF_POINT_TOP_MID 0x2
#define PSLR_AF_POINT_TOP_RIGHT 0x4
#define PSLR_AF_POINT_FAR_LEFT 0x8
#define PSLR_AF_POINT_MID_LEFT 0x10
#define PSLR_AF_POINT_MID_MID 0x20
#define PSLR_AF_POINT_MID_RIGHT 0x40
#define PSLR_AF_POINT_FAR_RIGHT 0x80
#define PSLR_AF_POINT_BOT_LEFT 0x100
#define PSLR_AF_POINT_BOT_MID 0x200
#define PSLR_AF_POINT_BOT_RIGHT 0x400
typedef enum {
PSLR_WHITE_BALANCE_MODE_AUTO,
PSLR_WHITE_BALANCE_MODE_DAYLIGHT,
PSLR_WHITE_BALANCE_MODE_SHADE,
PSLR_WHITE_BALANCE_MODE_CLOUDY,
PSLR_WHITE_BALANCE_MODE_FLUORESCENT_DAYLIGHT_COLOR,
PSLR_WHITE_BALANCE_MODE_FLUORESCENT_DAYLIGHT_WHITE,
PSLR_WHITE_BALANCE_MODE_FLUORESCENT_COOL_WHITE,
PSLR_WHITE_BALANCE_MODE_TUNGSTEN,
PSLR_WHITE_BALANCE_MODE_FLASH,
PSLR_WHITE_BALANCE_MODE_MANUAL,
PSLR_WHITE_BALANCE_MODE_MANUAL_2,
PSLR_WHITE_BALANCE_MODE_MANUAL_3,
PSLR_WHITE_BALANCE_MODE_KELVIN_1,
PSLR_WHITE_BALANCE_MODE_KELVIN_2,
PSLR_WHITE_BALANCE_MODE_KELVIN_3,
PSLR_WHITE_BALANCE_MODE_FLUORESCENT_WARM_WHITE,
PSLR_WHITE_BALANCE_MODE_CTE,
PSLR_WHITE_BALANCE_MODE_MULTI_AUTO,
PSLR_WHITE_BALANCE_MODE_MAX
} pslr_white_balance_mode_t;
typedef enum {
PSLR_IMAGE_FORMAT_JPEG,
PSLR_IMAGE_FORMAT_RAW,
PSLR_IMAGE_FORMAT_RAW_PLUS,
PSLR_IMAGE_FORMAT_MAX
} pslr_image_format_t;
resolution
: Number in megapixel
typedef enum {
PSLR_JPEG_IMAGE_TONE_NONE = -1,
PSLR_JPEG_IMAGE_TONE_NATURAL,
PSLR_JPEG_IMAGE_TONE_BRIGHT,
PSLR_JPEG_IMAGE_TONE_PORTRAIT,
PSLR_JPEG_IMAGE_TONE_LANDSCAPE,
PSLR_JPEG_IMAGE_TONE_VIBRANT,
PSLR_JPEG_IMAGE_TONE_MONOCHROME,
PSLR_JPEG_IMAGE_TONE_MUTED,
PSLR_JPEG_IMAGE_TONE_REVERSAL_FILM,
PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS,
PSLR_JPEG_IMAGE_TONE_RADIANT,
PSLR_JPEG_IMAGE_TONE_CROSS_PROCESSING,
PSLR_JPEG_IMAGE_TONE_FLAT,
PSLR_JPEG_IMAGE_TONE_AUTO,
PSLR_JPEG_IMAGE_TONE_MAX
} pslr_jpeg_image_tone_t;
typedef enum {
PSLR_DRIVE_MODE_SINGLE,
PSLR_DRIVE_MODE_CONTINUOUS_HI,
PSLR_DRIVE_MODE_SELF_TIMER_12,
PSLR_DRIVE_MODE_SELF_TIMER_2,
PSLR_DRIVE_MODE_REMOTE,
PSLR_DRIVE_MODE_REMOTE_3,
PSLR_DRIVE_MODE_CONTINUOUS_LO,
PSLR_DRIVE_MODE_MAX
} pslr_drive_mode_t;
typedef enum {
PSLR_RAW_FORMAT_PEF,
PSLR_RAW_FORMAT_DNG,
PSLR_RAW_FORMAT_MAX
} pslr_raw_format_t;
typedef enum {
PSLR_COLOR_SPACE_SRGB,
PSLR_COLOR_SPACE_ADOBERGB,
PSLR_COLOR_SPACE_MAX
} pslr_color_space_t;
This command returns 24 bytes representing 6 32-bit numbers. The numbers represents year, month, day, hour, minute, and sec.
This command modifies one setting at the selected offset. Value is a four-byte number (Big-Endian for older, Little-Endian for newer cameras) between 0 and 255.
This command returns a 4-byte number (Big-Endian for older, Little-Endian for newer cameras). The represented value is between 0 and 255.
When turn on the debug mode, the arg0
and arg1
should be 0x01
;
When turn off the debug mode, arg{0-3}
should all be zero.
mode
is 3 when turn on/off the debug mode.