Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/** \file
* PTP handlers to extend Magic Lantern to the USB port.
*
* These handlers are registered to allow Magic Lantern to interact with
* a PTP client on the USB port.
*/
#include "dryos.h"
#include "ptp.h"
#include "ptp-extra.h"
#include "tasks.h"
#include "menu.h"
#include "raw.h"
#include "bmp.h"
#include "property.h"
#include "module.h"
#include "lens.h"
#include "shoot.h"
#include "version.h"
#include "chdk-dng.h"
#include "powersave.h"
static PROP_INT(PROP_ISO, prop_iso);
static PROP_INT(PROP_SHUTTER, prop_shutter);
static void* my_single_frame;
static int get_a_frame = 0;
static void* get_lv()
{
// See also silent_pic_take_fullres(int interactive)
force_liveview();
raw_lv_request();
msleep(50);
raw_lv_release();
msleep(50);
raw_update_params();
return &raw_info;
}
static int getBuffers(struct memSuite * hSuite)
{
struct memChunk * hChunk = (void*) GetFirstChunkFromSuite(hSuite);
void* ptr = (void*) GetMemoryAddressOfMemoryChunk(hChunk);
while (1)
{
void* ptr0 = (void*) GetMemoryAddressOfMemoryChunk(hChunk);
int size = GetSizeOfMemoryChunk(hChunk);
int used = ptr - ptr0;
int remain = size - used;
//~ printf("remain: %x\n", remain);
/* the EDMAC might write a bit more than that,
* so we'll use a small safety margin (2 extra lines) */
if (remain < raw_info.frame_size + 2 * raw_info.pitch)
{
/* move to next chunk */
hChunk = GetNextMemoryChunk(hSuite, hChunk);
if (!hChunk)
{
//~ printf("no more memory\n");
break;
}
ptr = (void*) GetMemoryAddressOfMemoryChunk(hChunk);
//~ printf("next chunk: %x %x\n", hChunk, ptr);
continue;
}
else /* alright, a new frame fits here */
{
//~ printf("FRAME %d: hSuite=%x hChunk=%x ptr=%x\n", count, hSuite, hChunk, ptr);
my_single_frame = ptr;
return 0;
/*ptr = ptr + raw_info.frame_size;
if (count >= SP_BUFFER_SIZE)
{
//~ printf("we have lots of RAM, lol\n");
break;
}
*/
}
}
return 1;
}
static void fill_uint32(char* data, uint32_t value) {
uint8_t* d = (uint8_t*)data;
*d = value & 0xFF; value >>= 8; d++;
*d = value & 0xFF; value >>= 8; d++;
*d = value & 0xFF; value >>= 8; d++;
*d = value & 0xFF;
}
PTP_HANDLER( PTP_EXTRA_CODE, 0 )
{
struct ptp_msg msg = {
.id = PTP_RC_OK,
.session = session,
.transaction = transaction,
.param_count = 4,
.param = { 1, 2, 0xdeadbeef, 3 },
};
// handle command
char* mydata = NULL;
size_t thumbnail_size = 0;
char* rawadr = NULL;
struct memSuite * hSuite1 = NULL;
switch ( param1 )
{
case PTP_EXTRA_HelloWorld:
msg.param_count = 2;
msg.param[0] = PTP_EXTRA_VERSION_MAJOR;
msg.param[1] = PTP_EXTRA_VERSION_MINOR;
break;
case PTP_EXTRA_TakePicture:
#if defined(CONFIG_EOSM)
call("Release");
#endif
msg.param_count = 1;
msg.param[0] = 0;
break;
case PTP_EXTRA_GetLV:
hSuite1 = srm_malloc_suite(1);
if(!hSuite1)
{
msg.id = PTP_RC_GeneralError;
msg.param[0] = 0;
}
int raw_flag = 1;
raw_lv_request();
if (!raw_update_params())
{
msg.id = PTP_RC_GeneralError;
msg.param[0] = 1;
goto cleanup;
}
if(getBuffers(hSuite1))
{
msg.id = PTP_RC_GeneralError;
msg.param[0] = 2;
goto cleanup;
}
memset(my_single_frame, 0, raw_info.frame_size);
struct raw_info local_raw_info = raw_info;
get_a_frame = 1;
int loop_ctr = 0;
while(get_a_frame == 1)
{
loop_ctr++;
msleep(20);
if (!lv)
{
get_a_frame = 0;
break;
}
}
if(get_a_frame != 2)
{
msg.id = PTP_RC_GeneralError;
msg.param[0] = 3;
get_a_frame = 0;
goto cleanup;
}
raw_lv_release(); raw_flag = 0;
//raw_force_aspect_ratio_1to1();
//
local_raw_info.buffer = my_single_frame;
msg.param[0] = local_raw_info.jpeg.width;
msg.param[1] = local_raw_info.jpeg.height;
create_dng_header(&local_raw_info);
create_thumbnail(&local_raw_info);
thumbnail_size = dng_th_width*dng_th_height*3;
mydata = malloc(dng_header_buf_size + thumbnail_size + local_raw_info.frame_size );
memcpy(mydata,dng_header_buf,dng_header_buf_size);
memcpy(mydata + dng_header_buf_size, thumbnail_buf,thumbnail_size);
rawadr = (void*) local_raw_info.buffer;
reverse_bytes_order(rawadr, local_raw_info.frame_size);
memcpy(mydata + dng_header_buf_size + thumbnail_size, rawadr, local_raw_info.frame_size);
srm_free_suite(hSuite1);
my_single_frame = NULL;
send_ptp_data(context, mydata, dng_header_buf_size + thumbnail_size + local_raw_info.frame_size);
free(mydata);
free_dng_header();
redraw();
cleanup:
if (raw_flag)
raw_lv_release();
break;
/*
case PTP_EXTRA_GetLVFull:
prop_iso = lens_info.raw_iso;
if (shooting_mode != SHOOTMODE_M || (prop_iso == 0 || prop_shutter == 0))
{
msg.param_count = 1;
msg.param[0] = 1;
break;
}
if (!lv && !LV_PAUSED && gui_state != GUISTATE_QR) force_liveview();
PauseLiveView();
//gui_uilock(UILOCK_EVERYTHING);
//clrscr();
vram_clear_lv();
display_off();
//struct JobClass * copy_job = 0;
//void* copy_buf = 0;
struct JobClass * job = (void*) call("FA_CreateTestImage");
lens_info.job_state = 1;
info_led_on();
//int t0 = get_ms_clock_value();
call("FA_CaptureTestImage", job);
//int t1 = get_ms_clock_value();
//int capture_time = t1 - t0;
info_led_off();
lens_info.job_state = 0;
call("FA_DeleteTestImage", job);
msg.param[0] = raw_info.jpeg.width;
msg.param[1] = raw_info.jpeg.height;
create_dng_header(&raw_info);
create_thumbnail(&raw_info);
mydata = malloc(dng_header_buf_size + dng_th_width*dng_th_height*3 + raw_info.frame_size );
memcpy(mydata,dng_header_buf,dng_header_buf_size);
size_t thumbnail_size = dng_th_width*dng_th_height*3;
memcpy(mydata + dng_header_buf_size, thumbnail_buf,thumbnail_size);
rawadr = (void*) raw_info.buffer;
reverse_bytes_order(rawadr, raw_info.frame_size);
memcpy(mydata + dng_header_buf_size + thumbnail_size, rawadr, raw_info.frame_size);
send_ptp_data(context, mydata, dng_header_buf_size + thumbnail_size + raw_info.frame_size);
free(mydata);
free_dng_header();
break;
*/
default:
msg.id = PTP_RC_ParameterNotSupported;
break;
}
context->send_resp(
context->handle,
&msg
);
return 0;
}
unsigned int get_single_frame(unsigned int ctx)
{
if(get_a_frame != 1)
return 0;
if(my_single_frame == 0)
return 0;
raw_lv_redirect_edmac(my_single_frame);
get_a_frame=2;
return 0;
/*
if (!sp_running) return 0;
if (!sp_buffer_count) { sp_running = 0; return 0; };
if (!raw_lv_settings_still_valid()) { sp_running = 0; return 0; }
if (silent_pic_mode == SILENT_PIC_MODE_SLITSCAN)
{
silent_pic_raw_slitscan_vsync();
return 0;
}
// are we done?
if ((sp_num_frames >= sp_min_frames && !get_halfshutter_pressed()) || sp_num_frames >= sp_max_frames)
{
sp_running = 0;
return 0;
}
int next_slot = sp_num_frames % sp_buffer_count;
if (silent_pic_mode == SILENT_PIC_MODE_BEST_FOCUS)
{
next_slot = silent_pic_raw_choose_next_slot();
}
// Reprogram the raw EDMAC to output the data in our buffer (ptr)
raw_lv_redirect_edmac(sp_frames[next_slot % sp_buffer_count]);
sp_num_frames++;
bmp_printf(FONT_MED, 0, 60, "Capturing frame %d...", sp_num_frames);
return 0;
*/
}
MODULE_CBRS_START()
MODULE_CBR(CBR_VSYNC, get_single_frame, 0)
MODULE_CBRS_END()
@andreok

This comment has been minimized.

Copy link

@andreok andreok commented Dec 5, 2019

Hello natschil,

I would like to use your ML PTP extension for capturing silencing pictures via libgphoto2 for astrophotography.
Could you please upload also your ptp-extra.h?
Have you managed to make it work with libgphoto2 or libptp2?

Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.