diff options
author | Marcus Meissner <marcus@jet.franken.de> | 2017-05-06 13:11:52 +0200 |
---|---|---|
committer | Marcus Meissner <marcus@jet.franken.de> | 2017-05-06 13:11:52 +0200 |
commit | 3f0975f985890622ed5e9febebd6ea3a0c8b053c (patch) | |
tree | 6f98fcf67bf9baf512702d6c890b374de5df735e | |
parent | ea5018ec785780a43dd13cb92880112d3e583bda (diff) | |
download | libgphoto2-3f0975f985890622ed5e9febebd6ea3a0c8b053c.tar.gz |
draft implementation of Fuji capture support, after https://github.com/gphoto/libgphoto2/issues/133
-rw-r--r-- | camlibs/ptp2/config.c | 13 | ||||
-rw-r--r-- | camlibs/ptp2/library.c | 146 |
2 files changed, 146 insertions, 13 deletions
diff --git a/camlibs/ptp2/config.c b/camlibs/ptp2/config.c index eadb07a5d..0b758fbbf 100644 --- a/camlibs/ptp2/config.c +++ b/camlibs/ptp2/config.c @@ -479,19 +479,6 @@ camera_prepare_capture (Camera *camera, GPContext *context) GP_LOG_D ("prepare_capture"); switch (params->deviceinfo.VendorExtensionID) { - case PTP_VENDOR_FUJI: { - PTPPropertyValue propval; - - if (!have_prop(camera, PTP_VENDOR_FUJI, 0xd207)) - break; - if (!have_prop(camera, PTP_VENDOR_FUJI, 0xd208)) - break; - propval.u16 = 0x0002; - C_PTP_REP (ptp_setdevicepropvalue (params, 0xd207, &propval, PTP_DTC_UINT16)); - propval.u16 = 0x0200; - C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &propval, PTP_DTC_UINT16)); - break; - } case PTP_VENDOR_CANON: if (ptp_operation_issupported(params, PTP_OC_CANON_InitiateReleaseControl)) return camera_prepare_canon_powershot_capture(camera,context); diff --git a/camlibs/ptp2/library.c b/camlibs/ptp2/library.c index fe8b1b938..32d7c1423 100644 --- a/camlibs/ptp2/library.c +++ b/camlibs/ptp2/library.c @@ -3918,6 +3918,112 @@ camera_sony_capture (Camera *camera, CameraCaptureType type, CameraFilePath *pat return add_objectid_and_upload (camera, path, context, newobject, &oi); } +static int +camera_fuji_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) +{ + PTPParams *params = &camera->pl->params; + PTPPropertyValue propval; + PTPObjectHandles handles, beforehandles; + int tries; + uint32_t newobject; + + GP_LOG_D ("camera_fuji_capture"); + + C_PTP (ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0x000000, 0x000000, &beforehandles)); + + /* ask camera to listen to tethering commands instead of button */ + propval.u16 = 0x0002; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd207, &propval, PTP_DTC_UINT16)); + + /* focus */ + propval.u16 = 0x0200; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &propval, PTP_DTC_UINT16)); + C_PTP_REP(ptp_initiatecapture(params, 0x00000000, 0x00000000)); + + /* poll camera until it is ready */ + propval.u16 = 0x0001; + while (propval.u16 == 0x0001) { + ptp_getdevicepropvalue (params, 0xd209, &propval, PTP_DTC_UINT16); + GP_LOG_D ("XXX Ready to shoot? %X", propval.u16); + } + + /* shoot */ + propval.u16 = 0x0304; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &propval, PTP_DTC_UINT16)); + C_PTP_REP(ptp_initiatecapture(params, 0x00000000, 0x00000000)); + + /* poll camera until it is ready */ + propval.u16 = 0x0000; + while (propval.u16 == 0x0000) { + ptp_getdevicepropvalue (params, 0xd212, &propval, PTP_DTC_UINT64); + GP_LOG_D ("XXX Ready after shooting? %lx", propval.u64); + } + + /* duplicate the nikon broken capture, as we do not know how to get events yet */ + + tries = 5; + GP_LOG_D ("missing fuji objectadded events workaround"); + while (tries--) { + unsigned int i; + uint16_t ret = ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0x000000, 0x000000, &handles); + if (ret != PTP_RC_OK) + break; + + /* if (handles.n == params->handles.n) + * continue; + * While this is a potential optimization, lets skip it for now. + */ + newobject = 0; + for (i=0;i<handles.n;i++) { + unsigned int j; + PTPObject *ob; + + /* look if we saw the objecthandle before capture */ + for (j=0;j<beforehandles.n;j++) + if (beforehandles.Handler[j] == handles.Handler[i]) + break; + if (j != beforehandles.n) + continue; + + ret = ptp_object_want (params, handles.Handler[i], PTPOBJECT_OBJECTINFO_LOADED, &ob); + if (ret != PTP_RC_OK) { + GP_LOG_E ("object added, but not found?"); + continue; + } + /* A directory was added, like initial DCIM/100NIKON or so. */ + if (ob->oi.ObjectFormat == PTP_OFC_Association) + continue; + newobject = handles.Handler[i]; + /* we found a new file */ + break; + } + free (handles.Handler); + if (newobject) + break; + C_PTP_REP (ptp_check_event (params)); + sleep(1); + } + free (beforehandles.Handler); + if (!newobject) + GP_LOG_D ("fuji object added no new file found after 5 seconds?!?"); + + /* clear path, so we get defined results even without object info */ + path->name[0]='\0'; + path->folder[0]='\0'; + + if (newobject != 0) { + PTPObject *ob; + + C_PTP_REP (ptp_object_want (params, newobject, PTPOBJECT_OBJECTINFO_LOADED, &ob)); + strcpy (path->name, ob->oi.Filename); + sprintf (path->folder,"/"STORAGE_FOLDER_PREFIX"%08lx/",(unsigned long)ob->oi.StorageID); + get_folder_from_handle (camera, ob->oi.StorageID, ob->oi.ParentObject, path->folder); + /* delete last / or we get confused later. */ + path->folder[ strlen(path->folder)-1 ] = '\0'; + return gp_filesystem_append (camera->fs, path->folder, path->name, context); + } + return GP_ERROR; +} static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, @@ -4002,6 +4108,13 @@ camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, return camera_sony_capture (camera, type, path, context); } + if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_FUJI) && + ptp_operation_issupported(params, PTP_OC_InitiateCapture) + ) { + return camera_fuji_capture (camera, type, path, context); + } + + if (!ptp_operation_issupported(params,PTP_OC_InitiateCapture)) { gp_context_error(context, _("Sorry, your camera does not support generic capture")); @@ -4564,6 +4677,39 @@ camera_trigger_capture (Camera *camera, GPContext *context) return GP_OK; } + if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_FUJI) && + ptp_operation_issupported(params, PTP_OC_InitiateCapture) + ) { + PTPPropertyValue propval; + + /* ask camera to listen to tethering commands instead of button */ + propval.u16 = 0x0002; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd207, &propval, PTP_DTC_UINT16)); + + /* focus */ + propval.u16 = 0x0200; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &propval, PTP_DTC_UINT16)); + C_PTP_REP(ptp_initiatecapture(params, 0x00000000, 0x00000000)); + + /* poll camera until it is ready */ + propval.u16 = 0x0001; + while (propval.u16 == 0x0001) { + ptp_getdevicepropvalue (params, 0xd209, &propval, PTP_DTC_UINT16); + GP_LOG_D ("XXX Ready to shoot? %X", propval.u16); + } + + /* shoot */ + propval.u16 = 0x0304; + C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &propval, PTP_DTC_UINT16)); + C_PTP_REP(ptp_initiatecapture(params, 0x00000000, 0x00000000)); + + /* poll camera until it is ready */ + propval.u16 = 0x0000; + while (propval.u16 == 0x0000) { + ptp_getdevicepropvalue (params, 0xd212, &propval, PTP_DTC_UINT64); + GP_LOG_D ("XXX Ready after shooting? %lx", propval.u64); + } + } #if 0 if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) && |