diff --git a/camlibs/ptp2/library.c b/camlibs/ptp2/library.c index 35eb0dafa..16d2d8fed 100644 --- a/camlibs/ptp2/library.c +++ b/camlibs/ptp2/library.c @@ -3212,12 +3212,9 @@ camera_exit (Camera *camera, GPContext *context) /* Disable EOS capture now, also end viewfinder mode. */ if (params->eos_captureenabled) { if (camera->pl->checkevents) { - PTPCanon_changes_entry entry; - if ((exit_result = ptp_check_eos_events (params)) != PTP_RC_OK) goto exitfailed; - while (ptp_get_one_eos_event (params, &entry)) - GP_LOG_D ("missed EOS ptp type %d", entry.type); + GP_LOG_D ("missed %d EOS events", params->nrofbacklogentries); camera->pl->checkevents = 0; } if (params->inliveview && ptp_operation_issupported(params, PTP_OC_CANON_EOS_TerminateViewfinder)) diff --git a/camlibs/ptp2/ptp-pack.c b/camlibs/ptp2/ptp-pack.c index 1203e9ac2..86138814a 100644 --- a/camlibs/ptp2/ptp-pack.c +++ b/camlibs/ptp2/ptp-pack.c @@ -1751,6 +1751,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in int i = 0, entries = 0; const unsigned char *curdata = data; PTPCanon_changes_entry *ce; + char prefix[18 + 12] = { 0 }; /* strlen("event 123 (c1xx):") + 12 bytes to silence snprintf warning */ if (data==NULL) return 0; @@ -1763,7 +1764,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in break; } if (size < 8) { - ptp_debug (params, "size %d is smaller than 8.", size); + ptp_debug (params, "size %d is smaller than 8", size); break; } if ((size == 8) && (type == 0)) @@ -1775,16 +1776,17 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in if (type == PTP_EC_CANON_EOS_OLCInfoChanged) { unsigned int j; - entries++; if (size >= 12+2) { for (j=0;j<31;j++) if (dtoh16a(curdata+12) & (1<FORM.Enum.SupportedValue[j].u16 = ptp_unpack_EOS_ImageFormat( params, &xdata ); - ptp_debug (params, " option[%2d] of %x is 0x%04x", j, proptype, dpd->FORM.Enum.SupportedValue[j].u16); + ptp_debug (params, INDENT "prop %x option[%2d] == 0x%04x", proptype, j, dpd->FORM.Enum.SupportedValue[j].u16); } break; default: @@ -1928,12 +1929,12 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in switch (dpd->DataType) { #define XX( TYPE, CONV )\ if (sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt > xsize) { \ - ptp_debug (params, "size %lu does not match needed %u", sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt, xsize); \ + ptp_debug (params, "%s size %lu does not match needed %u", prefix, sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt, xsize); \ break; \ } \ for (j=0;jFORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \ - ptp_debug (params, " option[%2d] of %x is 0x%02x", j, proptype, CONV(xdata)); \ + ptp_debug (params, INDENT "prop %x option[%2d] == 0x%02x", proptype, j, CONV(xdata)); \ xdata += 4; /* might only be for propxtype 3 */ \ } \ break; @@ -1957,7 +1958,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in } case PTP_EC_CANON_EOS_PropValueChanged: { /* property info */ if (size < PTP_ece_Prop_Val_Data) { - ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Val_Data); + ptp_debug (params, "%s size %d is smaller than %d", prefix, size, PTP_ece_Prop_Val_Data); break; } @@ -1966,8 +1967,8 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in const unsigned char *xdata = &curdata[PTP_ece_Prop_Val_Data]; unsigned int xsize = size - PTP_ece_Prop_Val_Data; - ptp_debug (params, "event %3d: EOS prop %04x value changed, size %2d (%s)", - i, proptype, xsize, ptp_get_property_description(params, proptype)); + ptp_debug (params, "%s prop %04x value changed, size %2d (%s)", + prefix, proptype, xsize, ptp_get_property_description(params, proptype)); PTPDevicePropDesc *dpd = _lookup_or_allocate_canon_prop(params, proptype); @@ -2113,10 +2114,10 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in /* unknown props, listed from dump.... all 16 bit, but vals might be smaller */ case PTP_DPC_CANON_EOS_DPOFVersion: dpd->DataType = PTP_DTC_UINT16; - ptp_debug (params, " EOS prop %04x is unknown", proptype); + ptp_debug (params, INDENT "prop %04x is unknown", proptype); if (xsize > 2) for (j=0;jDataType = PTP_DTC_UINT8; - ptp_debug (params, " EOS prop %04x is unknown", proptype); + ptp_debug (params, INDENT "prop %04x is unknown", proptype); ptp_debug_data (params, xdata, xsize); /* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */ xdata += 4; @@ -2147,12 +2148,12 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in case PTP_DPC_CANON_EOS_GPSLogCtrl: case PTP_DPC_CANON_EOS_GPSDeviceActive: dpd->DataType = PTP_DTC_UINT32; - ptp_debug (params, " EOS prop %04x is unknown", proptype); + ptp_debug (params, INDENT "prop %04x is unknown", proptype); if (xsize % sizeof(uint32_t) != 0) - ptp_debug (params, " Warning: datasize modulo sizeof(uint32) is not 0: %lu", xsize % sizeof(uint32_t)); + ptp_debug (params, INDENT "Warning: datasize modulo sizeof(uint32) is not 0: %lu", xsize % sizeof(uint32_t)); if (xsize > 4) for (j=0;jFactoryDefaultValue.i32 = dtoh32a(xdata); dpd->CurrentValue.i32 = dtoh32a(xdata); - ptp_debug (params ," value of %x is %d (i32)", proptype, dpd->CurrentValue.i32); + ptp_debug (params, INDENT "prop %x value == %d (i32)", proptype, dpd->CurrentValue.i32); break; case PTP_DTC_UINT32: dpd->FactoryDefaultValue.u32 = dtoh32a(xdata); dpd->CurrentValue.u32 = dtoh32a(xdata); - ptp_debug (params ," value of %x is 0x%08x (u32)", proptype, dpd->CurrentValue.u32); + ptp_debug (params, INDENT "prop %x value == 0x%08x (u32)", proptype, dpd->CurrentValue.u32); break; case PTP_DTC_INT16: dpd->FactoryDefaultValue.i16 = dtoh16a(xdata); dpd->CurrentValue.i16 = dtoh16a(xdata); - ptp_debug (params," value of %x is %d (i16)", proptype, dpd->CurrentValue.i16); + ptp_debug (params, INDENT "prop %x value == %d (i16)", proptype, dpd->CurrentValue.i16); break; case PTP_DTC_UINT16: dpd->FactoryDefaultValue.u16 = dtoh16a(xdata); dpd->CurrentValue.u16 = dtoh16a(xdata); - ptp_debug (params," value of %x is 0x%04x (u16)", proptype, dpd->CurrentValue.u16); + ptp_debug (params, INDENT "prop %x value == 0x%04x (u16)", proptype, dpd->CurrentValue.u16); break; case PTP_DTC_UINT8: dpd->FactoryDefaultValue.u8 = dtoh8a(xdata); dpd->CurrentValue.u8 = dtoh8a(xdata); - ptp_debug (params," value of %x is 0x%02x (u8)", proptype, dpd->CurrentValue.u8); + ptp_debug (params, INDENT "prop %x value == 0x%02x (u8)", proptype, dpd->CurrentValue.u8); break; case PTP_DTC_INT8: dpd->FactoryDefaultValue.i8 = dtoh8a(xdata); dpd->CurrentValue.i8 = dtoh8a(xdata); - ptp_debug (params," value of %x is %d (i8)", proptype, dpd->CurrentValue.i8); + ptp_debug (params, INDENT "prop %x value == %d (i8)", proptype, dpd->CurrentValue.i8); break; case PTP_DTC_STR: { #if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */ @@ -2209,7 +2210,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in free (dpd->CurrentValue.str); dpd->CurrentValue.str = strdup( (char*)xdata ); #endif - ptp_debug (params," value of %x is '%s' (str)", proptype, dpd->CurrentValue.str); + ptp_debug (params, INDENT "prop %x value == '%s' (str)", proptype, dpd->CurrentValue.str); break; } default: @@ -2226,7 +2227,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in dpd->DataType = PTP_DTC_UINT16; dpd->FactoryDefaultValue.u16 = ptp_unpack_EOS_ImageFormat( params, &xdata ); dpd->CurrentValue.u16 = dpd->FactoryDefaultValue.u16; - ptp_debug (params," value of %x is 0x%04x (u16)", proptype, dpd->CurrentValue.u16); + ptp_debug (params, INDENT "prop %x value == 0x%04x (u16)", proptype, dpd->CurrentValue.u16); break; case PTP_DPC_CANON_EOS_CustomFuncEx: dpd->DataType = PTP_DTC_STR; @@ -2234,7 +2235,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in free (dpd->CurrentValue.str); dpd->FactoryDefaultValue.str = ptp_unpack_EOS_CustomFuncEx( params, &xdata ); dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str ); - ptp_debug (params," value of %x is %s", proptype, dpd->CurrentValue.str); + ptp_debug (params, INDENT "prop %x value == %s", proptype, dpd->CurrentValue.str); break; case PTP_DPC_CANON_EOS_FocusInfoEx: dpd->DataType = PTP_DTC_STR; @@ -2242,7 +2243,7 @@ ptp_unpack_EOS_events (PTPParams *params, const unsigned char* data, unsigned in free (dpd->CurrentValue.str); dpd->FactoryDefaultValue.str = ptp_unpack_EOS_FocusInfoEx( params, &xdata, xsize ); dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str ); - ptp_debug (params," value of %x is %s", proptype, dpd->CurrentValue.str); + ptp_debug (params, INDENT "prop %x value == %s", proptype, dpd->CurrentValue.str); break; /* case PTP_DPC_CANON_EOS_ShutterReleaseCounter: * There are 16 bytes sent by an R8, which look like 4 int numbers: 16, 1, 1000, 1000 @@ -2291,35 +2292,35 @@ static unsigned int olcsizes[0x15][13] = { if (olcver == 0) { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "OLC version is unknown"); - ptp_debug (params, "event %3d: OLC version is 0, skipping (might get set later)", i); + ptp_debug (params, "%s OLC version is 0, skipping (might get set later)", prefix); break; } if (olcver >= sizeof(olcsizes)/sizeof(olcsizes[0])) { - ptp_debug (params, "event %3d: OLC version is 0x%02x, assuming latest known", i, olcver); + ptp_debug (params, "%s OLC version is 0x%02x, assuming latest known", prefix, olcver); olcver = sizeof(olcsizes)/sizeof(olcsizes[0])-1; } mask = size >= 14 ? dtoh16a(curdata+8+4) : 0; - ptp_debug (params, "event %3d: EOS event OLCInfoChanged (size %d, version 0x%02x, mask 0x%04x)", i, size, olcver, mask); - if (size >= 0x8) { /* event info */ + ptp_debug (params, "%s OLCInfoChanged (size %d, version 0x%02x, mask 0x%04x)", prefix, size, olcver, mask); + if (size >= 8) { /* event info */ ptp_debug_data (params, curdata + 8, size - 8); } if (size < 14) { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "OLC size too small"); - ptp_debug (params, "event %3d: OLC unexpected size %d", i, size); + ptp_debug (params, "%s OLC unexpected size %d", prefix, size); break; } len = dtoh32a(curdata+8); if ((len != size-8) && (len != size-4)) { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "OLC size unexpected"); - ptp_debug (params, "event %3d: OLC unexpected size %d for blob len %d (not -4 nor -8)", i, size, len); + ptp_debug (params, "%s OLC unexpected size %d for blob len %d (not -4 nor -8)", prefix, size, len); break; } curoff = 8+4+4; - for (j = 0; j <= 12 ; j++) { + for (j = 0; j <= 12; j++) { unsigned int curmask = 1 << j; unsigned int cursize = MIN(olcsizes[olcver][j], size - curoff); if (curoff > size) @@ -2327,16 +2328,15 @@ static unsigned int olcsizes[0x15][13] = { if (!(mask & curmask)) continue; if (olcsizes[olcver][j] != cursize) { - ptp_debug (params, "event %3d: mask 0x%04x entry truncated (%d bytes), olcsizes table (%d bytes) wrong?", - i, curmask, cursize, olcsizes[olcver][j]); + ptp_debug (params, "%s mask 0x%04x entry truncated (%d bytes), olcsizes table (%d bytes) wrong?", + prefix, curmask, cursize, olcsizes[olcver][j]); } - ptp_debug (params, "event %3d: olcmask 0x%04x, %d bytes: %s", i, curmask, cursize, + ptp_debug (params, "event %3d:%04x: (olcmask) %d bytes: %s", i, curmask, cursize, ptp_bytes2str(curdata + curoff, cursize, "%02x ")); switch (curmask) { case CANON_EOS_OLC_BUTTON: { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "Button %x", dtoh16a(curdata+curoff)); - i++; break; } case CANON_EOS_OLC_SHUTTERSPEED: { @@ -2357,7 +2357,6 @@ static unsigned int olcsizes[0x15][13] = { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; ce[i].u.propid = proptype; - i++; break; } case CANON_EOS_OLC_APERTURE: { @@ -2378,7 +2377,6 @@ static unsigned int olcsizes[0x15][13] = { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; ce[i].u.propid = proptype; - i++; break; } case CANON_EOS_OLC_ISO: { @@ -2391,7 +2389,6 @@ static unsigned int olcsizes[0x15][13] = { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; ce[i].u.propid = proptype; - i++; break; } case 0x0040: { @@ -2405,7 +2402,6 @@ static unsigned int olcsizes[0x15][13] = { value/10, abs(value)%10, ptp_bytes2str(curdata + curoff + 3, olcsizes[olcver][j] - 3, "%02x ") ); - i++; break; } case 0x0010: @@ -2444,62 +2440,67 @@ static unsigned int olcsizes[0x15][13] = { * might be mask of focus points selected */ case 0x1000: /* mask 0x1000: 1 byte, 00 observed */ - /* mask 0x1000: 8 byte too on 5ds, version 0xb (has shuttercount inside) - axxel's 5Ds only contains 1 byte!?! */ default: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "OLCInfo event 0x%04x, %d bytes: %s", curmask, olcsizes[olcver][j], ptp_bytes2str(curdata + curoff, olcsizes[olcver][j], "%02x ")); - i++; break; } curoff += olcsizes[olcver][j]; + i++; } + i--; /* account for the i++ at the end of the outer loop */ break; } case PTP_EC_CANON_EOS_CameraStatusChanged: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS; ce[i].u.status = dtoh32a(curdata+8); - ptp_debug (params, "event %3d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8)); + ptp_debug (params, "%s CameraStatusChanged (size %d) = %d", prefix, size, dtoh32a(curdata+8)); params->eos_camerastatus = dtoh32a(curdata+8); break; case 0: /* end marker */ - if (size == 8) /* no output */ - break; - ptp_debug (params, "event %3d: EOS event 0, but size %d", i, size); + if (size != 8) /* no output */ + ptp_debug (params, "%s EOS event list null terminator is expected to have size 8 instead of %d", prefix, size); break; case PTP_EC_CANON_EOS_BulbExposureTime: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "BulbExposureTime %u", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_CTGInfoCheckComplete: /* some form of storage catalog ? */ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "CTGInfoCheckComplete 0x%08x", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_StorageStatusChanged: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "StorageStatusChanged 0x%08x", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_StorageInfoChanged: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "StorageInfoChanged 0x%08x", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_StoreAdded: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "StoreAdded 0x%08x", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_StoreRemoved: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; PTP_CANON_SET_INFO(ce[i], "StoreRemoved 0x%08x", dtoh32a(curdata+8)); + ptp_debug (params, "%s %s", prefix, ce[i].u.info); break; case PTP_EC_CANON_EOS_ObjectRemoved: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED; ce[i].u.object.oid = dtoh32a(curdata+8); + ptp_debug (params, "%s object %08x removed", prefix, dtoh32a(curdata+8)); break; default: switch (type) { #define XX(x) case PTP_EC_CANON_EOS_##x: \ - ptp_debug (params, "event %3d: unhandled EOS event "#x" (size %u)", i, size); \ + ptp_debug (params, "%s unhandled EOS event "#x" (size %u)", prefix, size); \ PTP_CANON_SET_INFO(ce[i], "unhandled EOS event "#x" (size %u)", size); \ break; XX(RequestGetEvent) @@ -2517,27 +2518,33 @@ static unsigned int olcsizes[0x15][13] = { XX(PowerZoomInfoChanged) #undef XX default: - ptp_debug (params, "event %3d: unknown EOS event %04x", i, type); + ptp_debug (params, "%s unknown EOS event", prefix); break; } if (size >= 0x8) { /* event info */ - ptp_debug_data (params, curdata, size); + ptp_debug_data (params, curdata + 8, size - 8); } ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; break; } curdata += size; i++; - if (i >= entries) { - ptp_debug (params, "BAD: i %d, entries %d", i, entries); + if (i > entries && datasize - (curdata - data) > 8) { + ptp_debug (params, "BAD: ran out of allocated slots (%d) for EOS events, %ld bytes left to parse", entries, datasize - (curdata - data)); + break; } } + + if (i != entries) + ptp_debug (params, "BAD: mismatch between allocated (%d) and parsed (%d) event entries", entries, i); + if (!i) { free (ce); ce = NULL; } *pce = ce; return i; + #undef INDENT } /* diff --git a/camlibs/ptp2/ptp.c b/camlibs/ptp2/ptp.c index 328a2eb85..3cbaef50c 100644 --- a/camlibs/ptp2/ptp.c +++ b/camlibs/ptp2/ptp.c @@ -200,9 +200,9 @@ ptp_debug_data(PTPParams *params, const uint8_t* data, int size) for (int k = 0; k < size; k += 16) { zero_lines = (size - k > 16 && memcmp(data + k, zeros, 16) == 0) ? zero_lines + 1 : 0; if (zero_lines < 2) - ptp_debug (params, " 0x%03x: %s", k, ptp_bytes2str(data + k, MIN(16, size - k), NULL)); + ptp_debug (params, " 0x%03x: %s", k, ptp_bytes2str(data + k, MIN(16, size - k), NULL)); else if (zero_lines == 2) - ptp_debug (params, " [...]: %s", ""); //ptp_bytes2str(zeros, 16, "%02x ")); + ptp_debug (params, " [...]: %s", ""); //ptp_bytes2str(zeros, 16, "%02x ")); } } diff --git a/camlibs/ptp2/ptp.h b/camlibs/ptp2/ptp.h index ecb463b06..633552281 100644 --- a/camlibs/ptp2/ptp.h +++ b/camlibs/ptp2/ptp.h @@ -4829,6 +4829,11 @@ ptp_operation_issupported(PTPParams* params, uint16_t operation) { uint32_t i=0; + /* The R5m2 fails to send a PTP response packet after the data packet of the GetDeviceInfoEx. + * This seems to be firmware bug present in version 1.0.0 and 1.0.1. See #1028. */ + if (operation == PTP_OC_CANON_EOS_GetDeviceInfoEx && !strcmp(params->deviceinfo.Model,"Canon EOS R5m2")) + return 0; + for (;ideviceinfo.OperationsSupported_len;i++) { if (params->deviceinfo.OperationsSupported[i]==operation) return 1;