Is there a full PTP protocol description somewhere? - Script Writing - CHDK Forum supplierdeeply

Is there a full PTP protocol description somewhere?

  • 9 Replies
  • 7719 Views
Is there a full PTP protocol description somewhere?
« on: 28 / November / 2019, 18:12:20 »
Advertisements
Hi chdk'ers, this is my first post!!! I'm working on implementing the PTP protocol in kotlin for some things I'm playing around with and the descriptions in ptp.h are helpful, but I have some points of confusion on the description I could use help with if anyone knows the answers off-hand.
  • I've noticed that Live view only returns a data message and not a response message. Is it standard for the PTP flow to not return a seperate response when data is returned (Can I expect the same behavior from GetMemory/etc...)?
  • The relationship between TempData and DownloadFile is confusing even with the description. As I read it, the flow looks like:
    • Send TempData command with Download (and possibly clear flag)
    • Get response from TempDataCommand
    • Send DownloadFile Command
    • Receive download file data (and at this point tempdata will be cleared if clear flag was included)
    • Send a data packet with the encoded filename
    Is that correct? It just seems a little confusing that the clear flag in the first command would execute on the DownloadFIle command but otherwise it makes sense to me.
  • RemoteCaptureGetData, I haven't gone too deep into this yet because deciphering the interplay between lua and ptp will take some work, it would be nice to see the typical flow for what is expected to be sent/recieved for a single retrieval. Based on the comment in ptp.h, so far I'm wondering what does "return param3 seek required to pos (-1 = no seek)" mean? Is that param3 supposed to be used somewhere on the client side or is it just informational?
  • PTP_CHDK_S_ERR_SCRIPTRUNNING = 0x1000, // script already running with NOKILL... Does this mean the previous call was run with the nokill flag and that makes it durable, or that the current call is run with the nokill flag and therefore errors out instead of killing the script that is running?

Other than that ptp looks pretty straightforward, thanks to all devs for the amazing work!!!
« Last Edit: 28 / November / 2019, 19:09:33 by npbenjohnson »

Re: Is there a full PTP protocol description somewhere?
« Reply #1 on: 28 / November / 2019, 19:19:54 »
I'm working on implementing the PTP protocol in kotlin for some things I'm playing around with and the descriptions in ptp.h are helpful, but I have some points of confusion on the description I could use help with if anyone knows the answers off-hand.
......
Other than that ptp looks pretty straightforward, thanks to all devs for the amazing work!!!
So, it's just barely possible that @reyalp might be able to help here. He should be around in about an hour or so.  :haha
Ported :   A1200    SD940   G10    Powershot N    G16

*

Offline reyalp

  • ******
  • 14080
Re: Is there a full PTP protocol description somewhere?
« Reply #2 on: 28 / November / 2019, 20:17:29 »
Hi chdk'ers, this is my first post!!! I'm working on implementing the PTP protocol in kotlin for some things I'm playing around with and the descriptions in ptp.h are helpful, but I have some points of confusion on the description I could use help with if anyone knows the answers off-hand.
Welcome. There isn't really a description beyond what's in ptp.h and live_view.h. If you want working (I hope  :-[) examples, you can refer to the ptp_chdk_* functions in the chdkptp client source http://subversion.assembla.com/svn/chdkptp/trunk/ptp.c

Quote
I've noticed that Live view only returns a data message and not a response message. Is it standard for the PTP flow to not return a seperate response when data is returned (Can I expect the same behavior from GetMemory/etc...)?
It varies. CHDK ptp.h should describe the behavior of each operation, if something is wrong or unclear, feel free to post here. 

PTP_CHDK_GetDisplayData actually returns total size param 1, though the client should also be able to determine this in the data phase.
PTP_CHDK_GetMemory returns everything in the data phase.
PTP_CHDK_ReadScriptMsg returns various attributes of the message in return params, and only the message body as data.
 
Quote
The relationship between TempData and DownloadFile is confusing even with the description.
Yes.
Quote
As I read it, the flow looks like:
Send TempData command with Download (and possibly clear flag)
It should set PTP_CHDK_TD_DOWNLOAD, and the data phase should be the filenname.

For download, the clear flag is not actually used. The filename will be cleared and free'd automatically in the PTP_CHDK_DownloadFile despite what the comments say. (hmm, I should fix that)

And in fact, there is currently no *other* use of TempData. This was a very early part of the protocol and it was assumed other operations would need something similar, but so far they haven't.

Quote
Get response from TempDataCommand
It doesn't return parameters, but you should check for RC_OK
Quote
Send DownloadFile Command
Receive download file data (and at this point tempdata will be cleared if clear flag was included)
As above, it will be cleared no matter what.
Quote
Send a data packet with the encoded filename
The file name was sent in the TempData command, before Download. That's whole reason it is needed, because PTP only allows bulk data in one direction.

Quote
RemoteCaptureGetData, I haven't gone too deep into this yet because deciphering the interplay between lua and ptp will take some work, it would be nice to see the typical flow for what is expected to be sent/recieved for a single retrieval.
You can see some of this if you use the remoteshoot command in chdkptp with cli_verbose=2
However, be warned that different camera models behave differently.

Quote
Based on the comment in ptp.h, so far I'm wondering what does "return param3 seek required to pos (-1 = no seek)" mean? Is that param3 supposed to be used somewhere on the client side or is it just informational
Unfortunately, it's inherently complicated (for jpeg) because of how it's hooked into the Canon firmware. See platform/generic/filewrite.c and core/remotecap.c in the CHDK source.

Some background:
jpeg remote shoot is implemented by hooking the Canon filewrite firmware task (process/thread) that would normally write the file to the SD card. We modify it to replace calls to open(), write(), seek(), close() with our own functions. At certain points, we block the calling task (which thinks it's writing to the SD card) until the PTP client asks* for a chunk. Then we send the data that would been written in the write() call over PTP instead. When PTP transaction is done, we allow the filewrite task to continue.

The behavior of the Canon filewrite task has varied over the years. Some models just sequentially write chunks. Others open, close and seek between writes. Because client is essentially just pretending it's the filesystem, it needs to replicate the seek calls on the received data.

So the seek described in return param3 must cause the data to be written the specified offset in the file. See chdku.rc_handler_file in chdkptp/lua/chdku.lua

Note that CHDK raw/DNG is much simpler. In that case, we control the writing and have the entire raw image in memory, so it's just the header (for DNG) and data in single chunks.

* We don't have PTP events / interrupts on the camera side, so everything is done by polling
Quote
PTP_CHDK_S_ERR_SCRIPTRUNNING = 0x1000, // script already running with NOKILL... Does this mean the previous call was run with the nokill flag and that makes it durable, or that the current call is run with the nokill flag and therefore errors out instead of killing the script that is running?
No, the NOKILL determines how any existing, running script is handled when you try to run a new one:
Code: [Select]
#define PTP_CHDK_SCRIPT_FL_NOKILL           0x100 // if script is running return error instead of killing
If a script is already running and you call PTP_CHDK_ExecuteScript, the default behavior is to silently kill the running script. If you specify NOKILL, then it returns an error instead.

Silently clobbering was the original behavior, but in practice it's often not what you want, and calling PTP_CHDK_ScriptStatus before every script execution added a lot of overhead.
Don't forget what the H stands for.

Re: Is there a full PTP protocol description somewhere?
« Reply #3 on: 28 / November / 2019, 20:28:15 »
Thanks for the quick response, that cleared up everything I was stuck on


Re: Is there a full PTP protocol description somewhere?
« Reply #4 on: 29 / November / 2019, 00:44:06 »
Stuck on something new, I have executescript and readscriptmessage working, but when I try to run write_usb_msg("foo") through ptp execute script, when I read the message I get:

 :1: attempt to call global 'write_usb_message' (a nil value)

Do I need to require something to make that function available?

(I'm using chdk 1.4 if that is relevant)

*

Offline reyalp

  • ******
  • 14080
Re: Is there a full PTP protocol description somewhere?
« Reply #5 on: 29 / November / 2019, 00:51:50 »
Stuck on something new, I have executescript and readscriptmessage working, but when I try to run write_usb_msg("foo") through ptp execute script, when I read the message I get:

 :1: attempt to call global 'write_usb_message' (a nil value)
The function is "write_usb_msg" not "write_usb_message" as in the quoted error message. It's available by default.
Don't forget what the H stands for.

Re: Is there a full PTP protocol description somewhere?
« Reply #6 on: 29 / November / 2019, 00:58:43 »
 :-X thanks, that was it, my internal monologue is leaking into the code, time to quit for the night

*

Offline reyalp

  • ******
  • 14080
Re: Is there a full PTP protocol description somewhere?
« Reply #7 on: 29 / November / 2019, 15:30:26 »
:-X thanks, that was it, my internal monologue is leaking into the code, time to quit for the night
We've all been there. I, uh, may or may not have looked at the source to be sure what the actual name was  :haha

If you are writing a client, you might find the chdkptp rlibs.lua code useful. It's a collection of camera side code in a simple module system. chdkptp con:exec/execwait takes a list of rlibs names, which are combined with the supplied code and sent to the camera. Complicated stuff like shooting and traversing directory trees is mostly in the rlib code, so something like the shoot command will end up just doing con:execwait("rlib_shoot({options...})",{libs={'serialize_msgs','rlib_shoot'}})

The individual rlib modules are mostly not chdkptp specific. A few worth mentioning:
serialize_msgs overrides the default usb_msg_table_to_string so table return values and messages are formatted as Lua table constructors, rather than the default simple text format. For chdkptp, this means the client and camera can transparently exchange Lua values. For a non-Lua client, it could probably modified fairly easily to output something like JSON or YAML

msg_batcher is used by rlib modules that need to send a lot of data. The cameras have VERY limited free heap memory (sometimes just a few hundred KB) so for just listing a full directory can trigger an out of memory error if you try to send it all at once. msg_batcher collects results in a table and sends a batch once a certain number have been collected. Sending thousands of results one message at a time would be slow.

msg_shell is an example of a long running script that listens for messages. It can be extended at run time just by adding functions to msg_shell.cmds. This is useful because CHDK script state like key presses and shooting overrides are only preserved while a given script is running. Each ExecuteScript is a new script on the camera, so if you use you send just press('shoot_half'),  shoot_half will be released immediately. Using something like msg_shell, it will stay pressed until you send a release or the script end. The exec message in msg_shell lets you run arbitrary lua code by sending a message
exec ... lua code here
Don't forget what the H stands for.


Re: Is there a full PTP protocol description somewhere?
« Reply #8 on: 09 / December / 2019, 23:17:00 »
Thanks, checking out that rlibs stuff was helpful, I got jpeg remotecapture and live view working and took a bit of a break. I want to work on raw capture now, and I found the relevant docs/.c/.h files, but I'm still not understanding the basics.

From ptp.h, I understand that requesting the DNG Header and Raw data is separate, but does this mean that the raw data is just packed pixels with no metadata?

Is there a description of the DNG header anywhere or can someone suggest some reference material for tiff/exif/dng? I don't know c well enough to pull it from code unless it's in an obvious struct, and I can't follow the chdkptp lua code because it looks like a lot of utility methods accessing a shared state object to do lua table or c interop operations I don't understand. And all I can find on google is "buy adobe's 60 page tiff/ep ISO document"


*

Offline reyalp

  • ******
  • 14080
Re: Is there a full PTP protocol description somewhere?
« Reply #9 on: 10 / December / 2019, 01:17:15 »
From ptp.h, I understand that requesting the DNG Header and Raw data is separate, but does this mean that the raw data is just packed pixels with no metadata?
Yes. raw is just straight from the framebuffer, in packed little endian format. This is exactly what "CHDK  raw" is if you don't have DNG enabled (commonly saved with a .CRW extension, but not in Canon's CRW format).

Quote
Is there a description of the DNG header anywhere or can someone suggest some reference material for tiff/exif/dng? I don't know c well enough to pull it from code unless it's in an obvious struct, and I can't follow the chdkptp lua code because it looks like a lot of utility methods accessing a shared state object to do lua table or c interop operations I don't understand. And all I can find on google is "buy adobe's 60 page tiff/ep ISO document"
The final TIFF EP document isn't is available, but you can find earlier tiff specs (https://www.loc.gov/preservation/digital/formats/fdd/fdd000022.shtml) and the Adobe DNG spec (https://helpx.adobe.com/photoshop/digital-negative.html) is available freely. Between those, you should be able to get what you need.
The tiff structure is pretty straightforward, and you should only need a values from IFD0 if you just want to make a valid image.

Or, you can cheat: Swap the byte order of the raw data, concatenate the header, a (possibly blank) 128x96 8bpp thumbnail, and the raw data together and call it done. This is  what chdkptp used to do before r402 https://app.assembla.com/spaces/chdkptp/subversion/commits/402
This will break if we ever change the thumbnail size though.

You can also use chdkptp to inspect the DNG tags, like
Code: [Select]
dngload test.dng
dnginfo -ifd=0 -r

To see data stored outside of the tags, add -vals

You and use Adobe's dng_validate to verify the files are OK.
Don't forget what the H stands for.

 

Related Topics