#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();