https://bitbucket.org/daniel_fort/magic-lantern
Raw File
Tip revision: 180c70bf48fdf65d64002a67f8575e79262cefa6 authored by a1ex on 26 September 2014, 07:48:28 UTC
Close branch full-res-mlvi-fix.
Tip revision: 180c70b
ptp.h
#ifndef _ptp_h_
#define _ptp_h_

#include "dryos.h"
/** \file
 * PTP protocol and interface.
 *
 * The PTP protocol defines how the camera and a host computer communicate
 * over USB.  It defines operations and properties, and is callback driven.
 * Handlers for operations can be registered by calling ptp_register_handler()
 * and will be called when the host initiates that operation.
 */

/** \group PTP IDs
 *
 * These are some of the "well known" Canon PTP commands.
 * @{
 */
#define PTP_FM_OBJECTSIZE       0x910a
#define PTP_SET_DEVICE_PROP     0x9110
#define PTP_HD_CAPACITY         0x911a
#define PTP_GUI_OFF             0x911b
#define PTP_LCD_ON              0x911c
#define PTP_911E                0x911e  // unknown
#define PTP_UPDATE_FIRMARE      0x911f
#define PTP_LV_DATA             0x9153
#define PTP_LV_ZOOM_MAYBE       0x9154
#define PTP_LV_ZOOM             0x9158
#define PTP_LV_AFFRAME          0x915a
#define PTP_AF_START            0x9160
#define PTP_FAPI_MESSAGE_TX     0x91fe

// results
#define PTP_RC_OK               0x2001
#define PTP_RC_ERROR            0x2002

#define PTP_RC_GeneralError     0x2002
#define PTP_RC_ParameterNotSupported 0x2006

#define BUF_SIZE 128 * 1024

/** @} */

struct ptp_handle;

/** PTP message on the USB wire.
 *
 */
struct ptp_msg
{
	uint32_t                id;
	uint32_t                session;
	uint32_t                transaction;
	uint32_t                param_count;
	uint32_t                param[ 5 ];
} __attribute__((packed));

SIZE_CHECK_STRUCT( ptp_msg, 0x24 );


/** DryOS PTP callback context.
 *
 * When a handler is registered it will be called with a ptp_context
 * as its first argument.  These callbacks are to be used to reply
 * to the host.
 */
struct ptp_context
{
	struct ptp_handle *     handle;         // off_0x00;

	int             (*send_data)(
			struct ptp_handle *     handle,
			void *          buf,
			int                     part_size,
			int             total_size,     // total_size should be 0 except for the first call
			int,                        // that's brainfuck for me...
			int,
			int
			);

	// off 0x08
	int             (*recv_data)(
			struct ptp_handle *     handle,
			void *                  buf,
			size_t                  len,
			void                    (*callback)(
				void *                  cb_priv,
				int                     status
				),
			void *                  cb_priv
			);

	// Sends a formatted buffer
	// \note format to be determined
	// off_0x0c
	int             (*send_resp)(
			struct ptp_handle *     handle,
			struct ptp_msg *        msg
			);

	// Returns length of message to receive
	// off 0x10
	int             (*get_data_size)(
			struct ptp_handle *     handle
			);
	// CHDK equiv: int (*get_data_size)(int handle);

	void * off_0x14; // int (*send_err_resp)(int handle, PTPContainer *resp); ?
	void * off_0x18; // priv to close handler?
	void * off_0x1c; // close?
};


/** DryOS function to register a USB PTP handler.
*/
extern uint32_t
ptp_register_handler(
		uint32_t                id,
		int                     (*handler)(
			void *                  priv,
			struct ptp_context *    context,
			void *                  r2, // unknown
			void *                  r3 // unknown
			),
		void *                  priv
		);


/** Magic Lantern PTP handler segment.
 *
 * \internal These are generated by the PTP_HANDLER() macro to
 * create a list of handlers that will be automatically registered
 * when Magic Lantern boots.
 */
struct ptp_handler
{
	uint32_t                id;
	void *                  handler;
	void *                  priv;
};


/** Register a compile-time Magic Lantern PTP handler.
 *
 * \internal Typically PTP_HANDLER() is a better choice.
 */
#define REGISTER_PTP_HANDLER( ID, HANDLER, PRIV ) \
	struct ptp_handler \
__attribute__((section(".ptp_handlers"))) \
__ptp_handler_##ID = { \
	.id                     = ID, \
	.handler                = HANDLER, \
	.priv                   = PRIV, \
}


/** Register a compile-time Magic Lantern PTP handler.
 *
 * Register a PTP handler with the ID.  Magic Lantern will automatically
 * call the DryOS functions to register all the handlers that are
 * in the .ptp_handlers segment.
 */
#define PTP_HANDLER( ID, PRIV ) \
	static int ptp_handler_##ID(); \
REGISTER_PTP_HANDLER( ID, ptp_handler_##ID, PRIV ); \
static int ptp_handler_##ID( \
		void *                  priv, \
		struct ptp_context *    context, \
		uint32_t                opcode, \
		uint32_t                session, \
		uint32_t                transaction, \
		uint32_t                param1, \
		uint32_t                param2, \
		uint32_t                param3, \
		uint32_t                param4, \
		uint32_t                param5 \
		) \

#endif

int send_ptp_data(struct ptp_context *data, const char *buf, int size);
int recv_ptp_data(struct ptp_context *data, char *buf, int size);

uint32_t ptp_register_all_handlers();

back to top