Camcorder USB Interface Analysis

Pure Digital's Camcorder for CVS

[camcorder pic]



Overview

According to the documentation for the Zoran COACH software, the camera can support the following protocols:
It's not known if this camcorder enables which, if any, of these interfaces.

A driver that looks promising is the Zoran zr364xx video driver for Linux -- a preliminary analysis shows that all the commands sent by that driver are valid commands for the cvs camcorder. Whether they do the right thing is another story.  The way these cameras transfer recorded files seems to be the traditional Bulk-Only Mass Storage format, kindof like a USB disk drive, but I haven't tried that yet (others have without success so far).

Another driver of interest is the UI43Api -- I see text referencing many of these commands in the firmware. You can download UI43Api.dll here.


Enabling the Full Interface
Like previous PureDigital cameras, the manufacturer has put in an obstacle that prevents you from retrieving your own videos.

Before unlocking the full interface, only 5 USB vendor-specific commands are allowed (I haven't explored the other non-vendor-specific commands; some used in device enumeration are obviously enabled to allow the host computer to talk to the device).

I haven't figured out why commands 92 and 9D are enabled by default, or what they do.

The basic unlocking procedure is to request a 128-byte challenge, determine the correct response (from a database or algorithm), and then send the correct 128-byte response back to the camera. Challenges and Responses are send 4 bytes at a time.

However, due to a possible flaw in the implementation, you can directly ask the camera for the correct response that it will take to unlock it. Maybe this isn't a flaw, though - a quick look at the code or any simple testing should have shown the behavior.


Three commands are used to unlock the interface:

Command 0xFE: Authentication Challenge
Field
Value
Description
Pipe
0
Control Pipe
bmRequestType
kUSBOut, kUSBVendor, kUSBInterface Write to Camera
bRequest
0x01

bValue
0x01fe
LSB = command (0xFE)
MSB doesn't matter
bIndex
0x0101
doesn't matter
length
4
send an int32
data[0-3]
index
see below

The index value (passed in the data) determines what value will be returned when Command 0xFF is called:
Other values are allowed, but they must be divisible by 4 (otherwise the processor generates an unaligned address fault and reboots). You get 4 bytes back per request:

Command 0xFF: Authentication Challenge Retval

Field
Value
Description
Pipe
0
Control Pipe
bmRequestType
kUSBIn, kUSBVendor, kUSBInterface Read From Camera
bRequest
0x01

bValue
0x00ff
LSB = command (0xFF)
MSB doesn't matter
bIndex
0xffff
doesn't matter
length
4
return value will be 32 bits.
When command 0xFE hasn't been called yet, this function will return "DD CC BB AA". This is the default value stored in the firmware. Otherwise, it will return the return value from command 0xFE.


Command 0xFA: Authentication Response

Field
Value
Description
Pipe
0
Control Pipe
bmRequestType
kUSBOut, kUSBVendor, kUSBInterface Write to Camera
bRequest
0x01

bValue
0x01fa
LSB = command (0xFA)
MSB doesn't matter
bIndex
0x0101
doesn't matter
length
8
sending two int32 values
data[0-3]
index
see below
data[4-7]
data
see below

The index value should range from 0 to 0x80. The correct response value can be determined for asking for a challenge value in the range of  0x80-0xFF.

Here's the pseudo-code to unlock the camera:

for(index = 0; index <= 0x80; index += 4) {
    issue_authentication_challenge_command(index + 0x80)
    data = issue_authentication_challenge_retval_command()
    issue_authentication_response(index, data)
}
/* now verify: */
issue_authentication_challenge_command(0x1a0)
assert(issue_authentication_challenge_retval_command() = 1)

USB Interface Unlocked - now what!?

I've verified that the camera is unlocked using the 0x1a0 challenge request.  So, now, theoretically, all the commands are enabled. By tracing the code, it doesn't look like this lock flag affects anything else (like the Mass Storage mode).

To me, the most interesting command to hack around with is command 0xEF, the Monitor command that lets you do many things. The USB command handler does not do any error checking -- it simply passes a pointer to the data field to the command that processes monitor commands. I know that the function does this because I've seen other commands (built into the code) pass strings of commands to the same routine.  But, alas, no love. I suspect that maybe the UART needs to be initialized; otherwise the commands are forever waiting for log messages to go out before performing the actual command.

The download commands work great! So do many other commands, including change-directory and directory listing. The video camera is now effectively reusable.

All Vendor-Specific USB Commands

I've analyzed the function that takes data from the CamCmd Queue and calls a specific function based on the LSB of the bValue parameter.

The jump table is 8 bytes per entry -- 4 bytes for function address, and another 4 bytes for a parameter field. If this parameter is 1, a special function is called before the function is evaluated. The purpose of this function is not yet known. Otherwise, if the parameter is 0, execution proceeds directly to the function address in the jump table. I think a 0 means the function is meant to be read, and 1 means the function is meant to be written to.


Cmd
Jump
Table Param
Confirmed?
UI43Api Name  (credit: daBass)

Description (or strings referenced by code)
01 0

returns v0=00000000
02 0
I43_DPOFGetJobParamStr OnXmtFile aborted!
03 1

FsMediaOpen failed ( 0x%x )\n
FsMediaRead failed ( 0x%x )\n
04 1


05 1


06 0
I43_RestoreUSP (seem reasonable)
07 0
I43_UpdateUSP

08 0
I43_UpdateFSP

09 0
I43_RevertFSP

0a 1
I43_GetFreeParams
I43_SetFreeParams
Related to FSP and USP?  puwAppColdStorage
Commands 0a and 0b are related. Function 0a is probably GetFreeParams and 0b is probably SetFreeParams.
0b 1
I43_SetParam puwAppColdStorage
0c 1
I43_GetParamArray

0d 1
I43_GetParam

0e 1
I43_SendHCEMessage

0f 1
I43_SetTimer

10 0 Confirmed
I43_PowerOff
Camera turns off immediately, without usual power-off screen.
11 1
I43_SetVideoStd
I43_SetVideoFormat
I43_SetDisplayMode

12
not found

I43_ConfigUART

14 1
I43_UartLibConfig
Parameters: v0=1 byte @ 0, a2=16 bits @ 4, a1=16 bits @ 2 (if != 0 then configure & reset, otherwise just reset)?.
0=9600,1=14400,2=19200,3=38400,4=57600,5=15200,6=921600 aka warp speed
15 1
I43_UartLibRead

16 1
I43_UartLibWrite
"HCE Uart Write"
17 0
I43_LoadAWBCTLUT

18 1
I43_SendI2C

19 1
I43_GetI2C

1a 1
I43_ConfigI2CAccess

1b 1
I43_WriteI2CBurst

1c 1
I43_ReadI2CBurst

1e 1
I43_SetWBValues

1f 0
I43_SetMode
OnSetMode
"0x1f30 disables the viewfinder display and 0x1f70 enables it. By viewfinder display, I mean the ability of the camcorder to show live video on its lcd display captured from the ccd" (by ygfperson)
20 0
I43_SetAgcMode
I43_SetAEMode

21 1
I43_SetMeanBlackNoiseAuto
I43_SetMeanBlackNoise

22 1
I43_EnableISSPUBlock

23 0
I43_InitSensor
OnInitSensor
24 1
I43_SetBLE

25 1
I43_SetEdgeEnhancementLPF
I43_SetEdgeEnhancement

26 0
I43_SetWBMode

27 0
I43_GetWBValues

28 1
I43_SetAFThresholds
I43_SetAFRectangle

29 1
I43_LoadNLGFLUTResource
I43_LoadLscLUTResource
I43_LoadLcLUTResource
I43_LoadGammaLUTResource
I43_LoadBrightnessLUTResource

2a 0
I43_GetAFValues

2b 1

OnSetRgbToYuv
2c 0
I43_GetLumaHistogram

2d 0
I43_GetWeightedLuma

2e 0
I43_GetExposureValueStep

2f 0
I43_SetExposureDeviation

30 1
I43_PlaybackZoom

31 1
I43_LoadFontFile

32 1
I43_TuneDisplay

33 1
I43_DisplayWindow
AppDisplay
34 1
I43_ConfigImageResize
OnConfigImageResize
35 1
I43_ConfigCounter
AppConfigCounter - %d, %d, %d, %d
36 0
I43_SetCounter

37 1
I43_SelectGPIOEx

38 1
I43_ConfigGPIOEx

39 1
I43_GetGPIOEx

3a 1
I43_SetGPIOEx

3b 1
I43_DrawText
(confirmed this calls draw-text code)
3c 1
I43_DrawFile
OnDrawFile - %d, %s, %d, %d, %d, %d
3d 1
I43_SetGDA

3e 1
I43_DrawShape

3f 1
I43_DrawTextID
(confirmed this calls draw-text code)
40 1
I43_SetSensorWindow

41 1
I43_ConfigThumbnail

42 0
I43_ThumbnailShiftUp

43 0
I43_ThumbnailShiftDown
44 1
I43_GetFirstThumbnail

45 1
I43_SetOSDCLUTEx

46 1
I43_SetImageSize

47 1
I43_SetFormatConvert

48 1
I43_ConfigSubWindowsAF

49 0
I43_GetSubWindowsAF

4a 1
I43_ConfigHLRect

4b 1
I43_SetHLRect

4c 0
I43_ShowHLRect

4d 1
I43_LoadStringFile
AppLoadStringFile - %s
4e 1
I43_SetChromaCorrection

4f 1

display test patterns? (very doubtful)
50 0
I43_CaptureAudioMessage
51 1
I43_StopRecording

52 1
I43_AudioConfig

53 0
I43_PlayAudioMessage

54 0
I43_RecordPlayAudio
OnRecordPlayAudio
55 1
I43_Beep
takes two 16-bit words as data. Does some division with them. Is probably a beep. Many times something goes wrong, the camera freezes, then turns off.
57 1
I43_DPOFAddJob

58 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
59 1
I43_DPOFReadWriteFile

5a 0
I43_DPOFRelease

5b 1
I43_DPOFRemoveJob

5c 0
I43_DPOFGetFirstJobInFile

5d 1
I43_DPOFGetNextJob

5e 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
5f 1
I43_DPOFInit

60 0
I43_SetPreviewExposure
I43_SetPreviewAgc

61 0
I43_SetCaptureExposure
I43_SetCaptureAgc

62 1
I43_ConfigAEParams
OnConfigAeParams - %d %d %d. Parameters are 3 16-bit words
63 0
I43_SetCCD

64 0
I43_GetPreviewExposure
I43_GetPreviewAgc

65 0
I43_GetCaptureExposure
I43_GetCaptureAgc

66 1
I43_SetPreviewExposureLimits
OnSetPreviewExpLimit
67 1
I43_SetCaptureExposureLimits
OnSetCaptureExpLimit
68 1
I43_PipModeActivate
OnPipModeActivate %d %d
69 0
I43_GetDramImgParams

6a 1
I43_SetAWBCTC
OnSetAwbCtc - OK
6b 1
I43_SetAWBWeightLUTs

6c 1
I43_PipLayerCreate
OnPipLayerCreate layer %d %d %d %d %d
6d 0
I43_PipLayerDestroy
OnPipLayerDestroy layer %d
6e 1
I43_PipLayerShow
OnPipLayerShow layer %d %d
6f 1
I43_PipSetAttrib
OnPipSetAttrib %d %d %d %d %d %d
70 1
I43_SensorShutterConfig
takes 2 16-bit params.
71 1
I43_ConfigStrobePin
OnConfigStrobePin - %d %d %d
72 1
I43_ConfigRER
OnConfigRER - %d %d %d %d %d
73 0
I43_EnableRER

74 1
I43_ConfigFlashTrigger

75 0
I43_SetFlashTrigger

76 1
I43_SetCustomExposure

77 1
I43_SetOSDDisplayAttr

78 1
I43_OSDDrawFile
OnOsdDrawFile - %d %d %s %d %d %d %d
79 1
I43_OSDDrawShape

7a 1
I43_OSDTextOutID
(confirmed this calls draw-text code)
7b 1
I43_OSDTextOut
(confirmed this calls draw-text code)
7c 1
I43_OSDDrawTextID

7d 1
I43_OSDDrawText

7e 1
I43_DPOFSetHeaderParam

7f 1
I43_DPOFGetHeaderParam

80 1
I43_DPOFGetPrevJob

81 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
82 1
I43_DPOFSetJobParamInt

83 1
I43_DPOFGetJobParamInt

84 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
85 1
I43_DPOFSetJobParamStr

86 1
I43_DPOFAddSrcToJob

87 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
88 1
I43_DPOFRemoveSrc

89 1
I43_DPOFRemoveImage

8a 1
I43_DPOFGetImageData

8b 1
I43_DPOFSetSrcParam

8c 1
I43_DPOFGetFirstSrc

8d 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
8e 1
I43_DPOFGetNextSrc

8f 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
90 1
I43_DPOFGetPrevSrc
Takes one 32-bit word as a parameter
91 0

Only function is to returns 4 bytes at 0x80131340
** These commands are handled identically: 0x58, 5e, 81, 84, 87, 8d, 8f, & 91
92 1 mostly
Confirmed
I43_GetVideoCaptureImageSize
** ALLOWED BEFORE UNLOCKING **
AppPcVideoGetNoStreamSizes
Function is in file C:/dev/camera/Zcam/Commands/AppPcVideo.c
Accesses the file VidSize.BIN on the camcorder.
93 0 Confirmed I43_XMTFile
(Camera -> PC)
byBuffer, OnXmtFile - %s
Seems to take no input parameters in the data field (e.g. datalengh=0)
95 1 Confirmed I43_RCVFile
(PC -> Camera)
byBuffer, OnRcvFile - %s, Status %d
After setting name with 0xb1, provide this command with length of file about to be sent. Byte order of length is a bit screwy, in that I had to swap upper and lower two bytes with only this command. Bulk write the file's contents. (BillW)
96 1 DANGER!

May mess up flash memory, rendering camera unusable.
Returns strlen(??)+1
97 1
I43_DPOFGetSrcParam

98 0
I43_GetImage
GetImage_event, tx_event_flags_set
99 0 Confirmed
OnXmtThumbnail - 270 more bytes returned than XMTFile. (credit: Corscaria) These extra bytes are generated dynamically and not stored in the FLASH memory.
9a 1
I43_StartVideoCapture
On Get Video
9b 1
I43_XMTThumbnail

9c 0

Only function is to return 2 bytes at 0x80131340
9d 0

** ALLOWED BEFORE UNLOCKING **
Function may be related to audio or DeviceMassStorage.
ab 1
I43_SetDCFFreeChars
OnSetDcfFreeChars - %s
ac 1
I43_SetNextDCFKey
OnSetNextDcfKey - %d/%d   [DCF=device configuration file?]
ad 1
I43_GetDCFInfo
OnGetDcfInfo - %d %d %d %d %d
ae 1 partially
confirmed
I43_SetFileType
Use is optional, but if you use it with the file transfer commands the data must be 0x20 to recieve the file. I assume this is the FAT filetype. (BillW)
b0 1
I43_SetStatisticsPattern

b1 1 Confirmed I43_SetFileName
OnSetFileName - %s
Pass the null-terminated filename as data. Length includes null termination.
b2
1 Confirmed I43_SetCurrentImage
Pass an integer to command 0xb200 to select which video you are about to download (credit: Corscaria)
b3 0 Confirmed I43_GetCurrentImage
Listen on the bulk in to find out how many videos are on the camera (credit: Corscaria)
b5 1
I43_RegisterMedia

b6 0 partially confirmed
I43_GetStorageMediaStatus
I43_GetStorageMediaGeometry
OnGetStorageMediaStatus and OnGetStorageMediaGeometry.
See Minion's post.
b7 0 Confirmed
I43_FormatStorageMedia
OnFormatStorageMedia - %d
The camera should probably be rebooted after this command.
b8 1 Confirmed
I43_SetCurrentPath
Change directory (cd) command. I found that the data should be a null-terminated string, and the length should include that string. Do not include the drive letter. "/DCIM/100COACH" works fine. If you specify a directory that doesn't exist, that directory is created (which, if you pass in illegal filename, could be really interesting!)

Others have suggested that this should be a fixed length without null termination. DaBass's description: "takes as arguments 'name' in the data part and size of 'name' without \0"
b9 0
I43_GetFileAttributes
OnGetFileAttributes - OK
ba 1
I43_FileOperation
OnFileOperation FAIL - 0x%x
bc 0 Confirmed
I43_GetFirstFileAttribute
Here is some example data:
00 00 30 43 50 49 43 54 30 30 30 31 2e 41
56 49 00 18 20 00 8c 26 01 00 25 10 d8 32


This corresponds to file "75404 Jun 26 13:54 PICT0001.AVI"
REC,PICT0001.AVI,2005, 6,24,02,01,10,  114,30,    75404, 42

The fields mean:
00 00 30 43 - unknown. If this starts with 0f, there are no more files.
50 49 43 54 30 30 30 31 2e 41 56 49 - PICT0001.AVI (fixed width, padded with FF)
00 - filetype (00=normal file, 77=directory)
18 - unknown
20
- file attribute (10=directory, 20=file, just like FAT)
00
- unknown
8c 26 01 00 = 0x0001268c - file size
25 10 = modification time (dos format)
d8 32 = modification date (dos format)

For comparison, here is the FAT directory entry for the same file:
50 49 43 54 30 30 30 31 41 56 49 20 00 00 23 10  |PICT0001AVI ..#.|
d8 32 d8 32 00 00 25 10 d8 32 30 00 8c 26 01 00  |.2.2..%..20..&..|
bd 0 Confirmed
I43_GetNextFileAttribute
(used to get directory listing)
bf 0 Confirmed
I43_MountStorageMedia
OnMountStorageMedia - %d
Value is passed in other byte of command word.
0 is NO_NAME partition, 2-4 are resource partitions. (credit: daBass)
Don't set partition 1 - this may be the firmware partition and accessing it as if it was a FAT partion may damage it!
c6
not found
I43_AudioLoop
ca 0
I43_MotorGo

cb 1
I43_SetClock
OnSetClock - %d %d %d %d %d %d (16-bit parameters)
cc 0 Confirmed I43_GetClock
Returns 14 bytes as 7 16-bit words (in LSB/MSB endian order)
Example (each a few seconds apart, on my camera that apparently lost time):
84 07 05 00 1c 00 10 00 00 00 38 00 04 00
84 07 05 00 1c 00 10 00 01 00 11 00 04 00
84 07 05 00 1c 00 10 00 01 00 1c 00 04 00
0784 = year (1924), 0005=month, day, hour, minutes, seconds.
Last field unknown, but have seen 4 and 7 (day of week?)
cd 1
I43_MotorSet
OnMotorSet - %d %d %d %d %d %d %d %d %d %d %d
ce 1
I43_MotorConfig
OnMotorConfig - %d %d %d
cf 1
I43_ConfigButtonDrvEx
I43_ButtonEnable

d0 0 partially confirmed
I43_QueryStatus
Takes no paramenters and returns 2 16-bit words. A third word (not returned) is anded with 0xaf00 (this is presumably so the software knows the status has been read). Should be the same data returned by monitor command "getsr".
For an example of returned data, see Zapped's post
d2 0
I43_UsbConnect

d3 0
I43_SetUsbMode

da
not found
I43_WaitHostComSem
db
not found
I43_SignalHostComSem

dc
not found
I43_SetHostComData

dd
not found
I43_GetHostComData

df
not found
I43_PtpControl

e0 1
I43_PlaybackClipCmd
not necessarily this cmd: I43_PlaybackClipCmd - 0x%x 0x%x
e1 0
I43_SetCompressionRatio

e2 1
I43_SetSequenceLength

e3 0
I43_GetSequenceLength

e4 1
I43_SetImageEXIF

e5 1
I43_GetImageEXIF

e6 0
I43_GetImageAttributes
big cmd w/ fopen
e8 0

Returns 4 bytes of data stored at 0x8013bfa4 (set by command e5)
e9 0
I43_GetImageDateTime

ea 0
I43_ConfigDRAMCapture

eb 1
I43_ConfigCapture

ec 1
I43_ConfigNin1Mode

ed 0
I43_ConfirmStore
not necessarily this cmd: I43_ConfirmStore - %d
ee 0
I43_GetCaptureStatus

ef 1 Confirmed
I43_MonitorCmd
Issue a monitor command. No response is returned, but you can create files and read those.
Example: dumpf 134217728 8388608 chunk0.bin
f0 0
I43_WriteFlashBurst

f1 1 Confirmed
I43_ConfigMemAccess
from BillW: Sets flash memory access to the beginning of a partition within the extended partition.

Takes 2 passed integers and the second byte of the command word:
- The second byte of the command word, nn, determines the partition you are trying to access. 1=(ramdisk? cache?) 2=EBR+NO_NAME, 3=ResourcesA, 4=ResourcesB, 5=ResourcesC. Other values error or return partitions randomly. (EBR=Extended Boot Record)  [My analysis: only values 2, 3, 4, 5, 7 do anything & 7 is different from the rest.]
- The first data integer is the start location, offset from the start of the requested partition. Negative offsets don't appear to work, nor does reading past end of flash.
- The second data integer is the requested data size. Too large numbers will read past the end of the current partition on to the next partition, and if large enough, until the end of the flash
f2 0 Confirmed
I43_SetMem
from BillW: send with 0 bytes of data to initiate the flash transfer previously configured with 0xf2. Then write the flash transfer with bulk-out.
f3
?
Confirmed
GetMem
from BillW: send with 0 bytes of data to initiate the flash transfer previously configured with 0xf1. Then read the flash transfer with bulk-in.
f8 0
I43_GetCOACHVersion

f9 0
I43_UpgradeFlashFromCard

fa 1 Confirmed
I43_SetLong
Authentication response (written to camera to unlock)
** ALLOWED BEFORE UNLOCKING **
fc
not found
I43_UpgradeWav

fd 1
I43_EditImage
OnEditImage - %d %d %d %d %d
fe 1 Confirmed
Authentication challenge
** ALLOWED BEFORE UNLOCKING **
ff 0 Confirmed I43_GetLong
Authentication retval
** ALLOWED BEFORE UNLOCKING **


Additional links:

dakotamod aka brite_eye, mconsidine, and daBass have been systematically probing the camcorder with different USB commands.  Once I found evidence that only certain commands were enabled before unlocking, and that matched with what these people found (especially dakotamod, thanks!), I knew we were on to something and started USB experiments of my own.  daBass has a good low-level summary of his results so far.





My main CVS Camcorder analysis page
Info on the PV2 still disposable digital camera (also with LCD screen)
other systems I've played with
visit my homepage