diff --git a/camlibs/ptp2/ChangeLog b/camlibs/ptp2/ChangeLog index 4bace60fe..741fc0faa 100644 --- a/camlibs/ptp2/ChangeLog +++ b/camlibs/ptp2/ChangeLog @@ -9,6 +9,7 @@ copyright, lensname, serialnr, shuttercount, availableshots * ptp.c: decode EOS strings better * ptp-pack.c: dpd.GetSet adjustments. + * ptp-pack.c,config.c,ptp.c: Implemented EOS ImageSize and ImageFormat handling. 2009-05-26 Marcus Meissner diff --git a/camlibs/ptp2/config.c b/camlibs/ptp2/config.c index a5a199584..0e15bf3b7 100644 --- a/camlibs/ptp2/config.c +++ b/camlibs/ptp2/config.c @@ -1452,6 +1452,38 @@ static struct deviceproptableu16 canon_isospeed[] = { }; GENERIC16TABLE(Canon_ISO,canon_isospeed) +/* see ptp-pack.c:ptp_unpack_EOS_ImageFormat */ +static struct deviceproptableu16 canon_eos_image_format[] = { + { N_("RAW"), 0x0400, 0 }, + { N_("sRAW1"), 0x1400, 0 }, + { N_("sRAW2"), 0x2400, 0 }, + { N_("L/Fine"), 0x0300, 0 }, + { N_("L/Normal"), 0x0200, 0 }, + { N_("M/Fine"), 0x1300, 0 }, + { N_("M/Normal"), 0x1200, 0 }, + { N_("S/Fine"), 0x2300, 0 }, + { N_("S/Normal"), 0x2200, 0 }, + { N_("RAW + L/Fine"), 0x0403, 0 }, + { N_("sRAW1 + L/Fine"), 0x1403, 0 }, + { N_("sRAW2 + L/Fine"), 0x2403, 0 }, + { N_("RAW + M/Fine"), 0x0413, 0 }, + { N_("sRAW1 + M/Fine"), 0x1413, 0 }, + { N_("sRAW2 + M/Fine"), 0x2413, 0 }, + { N_("RAW + S/Fine"), 0x0423, 0 }, + { N_("sRAW1 + S/Fine"), 0x1423, 0 }, + { N_("sRAW2 + S/Fine"), 0x2423, 0 }, + { N_("RAW + L/Normal"), 0x0402, 0 }, + { N_("sRAW1 + L/Normal"), 0x1402, 0 }, + { N_("sRAW2 + L/Normal"), 0x2402, 0 }, + { N_("RAW + M/Normal"), 0x0412, 0 }, + { N_("sRAW1 + M/Normal"), 0x1412, 0 }, + { N_("sRAW2 + M/Normal"), 0x2412, 0 }, + { N_("RAW + S/Normal"), 0x0422, 0 }, + { N_("sRAW1 + S/Normal"), 0x1422, 0 }, + { N_("sRAW2 + S/Normal"), 0x2422, 0 }, +}; +GENERIC16TABLE(Canon_EOS_ImageFormat,canon_eos_image_format) + static struct deviceproptableu16 canon_eos_aeb[] = { { N_("off"), 0x0000, 0 }, { "+/- 1/3", 0x0003, 0 }, @@ -3294,7 +3326,8 @@ static struct submenu image_settings_menu[] = { { N_("Image Quality"), "imgquality", PTP_DPC_CompressionSetting, PTP_VENDOR_NIKON, PTP_DTC_UINT8, _get_Compression, _put_Compression}, { N_("Canon Image Quality"), "canonimgquality", PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, PTP_DTC_UINT8, _get_Canon_Quality, _put_Canon_Quality}, { N_("Canon Image Format"), "canonimgformat", PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, PTP_DTC_UINT8, _get_Canon_Capture_Format, _put_Canon_Capture_Format}, - { N_("Image Size"), "imgsize", PTP_DPC_ImageSize, 0, PTP_DTC_STR, _get_ImageSize, _put_ImageSize}, + { N_("EOS Image Format"), "imgformat", PTP_DPC_CANON_EOS_ImageFormat, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat, _put_Canon_EOS_ImageFormat}, + { N_("Image Size"), "imgsize", PTP_DPC_ImageSize, 0, PTP_DTC_STR, _get_ImageSize, _put_ImageSize}, { N_("Canon Image Size"), "canonimgsize", PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, PTP_DTC_UINT8, _get_Canon_Size, _put_Canon_Size}, { N_("ISO Speed"), "iso", PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_ISO, _put_Canon_ISO}, { N_("ISO Speed"), "iso", PTP_DPC_ExposureIndex, 0, PTP_DTC_UINT16, _get_ISO, _put_ISO}, diff --git a/camlibs/ptp2/ptp-pack.c b/camlibs/ptp2/ptp-pack.c index b9669f85e..a42762837 100644 --- a/camlibs/ptp2/ptp-pack.c +++ b/camlibs/ptp2/ptp-pack.c @@ -65,19 +65,19 @@ dtoh64p (PTPParams *params, uint64_t var) } static inline uint16_t -dtoh16ap (PTPParams *params, unsigned char *a) +dtoh16ap (PTPParams *params, const unsigned char *a) { return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a)); } static inline uint32_t -dtoh32ap (PTPParams *params, unsigned char *a) +dtoh32ap (PTPParams *params, const unsigned char *a) { return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a)); } static inline uint64_t -dtoh64ap (PTPParams *params, unsigned char *a) +dtoh64ap (PTPParams *params, const unsigned char *a) { return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a)); } @@ -1154,6 +1154,92 @@ ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]); } +static inline uint16_t +ptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data ) +{ + /* + EOS ImageFormat entries (of at least the 5DMII and the 400D ) look like this: + uint32: number of entries / generated files (1 or 2) + uint32: size of this entry in bytes (most likely allways 0x10) + uint32: image type (1 == JPG, 6 == RAW) + uint32: image size (0 == Large, 1 == Medium, 2 == Small) + uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW) + If number of entries is 2 the last uint32 repeat. + + example: + 0: 0x 1 + 1: 0x 10 + 2: 0x 6 + 3: 0x 1 + 4: 0x 4 + + The idea is to simply 'condense' these values to just one uint16 to be able to conveniontly + use the available enumeration facilities (look-up table). The image size and compression + values fully describe the image format. Hence we generate a uint16 with the four nibles set + as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression. + The above example would result in the value 0x1400. + */ + + const unsigned char* d = *data; + uint32_t n = dtoh32a( d ); + uint32_t l, s1, c1, s2 = 0, c2 = 0; + + if (n != 1 && n !=2) { + ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n); + return 0; + } + + l = dtoh32a( d+=4 ); + if (l != 0x10) { + ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l); + return 0; + } + + d+=4; /* skip type */ + s1 = dtoh32a( d+=4 ); + c1 = dtoh32a( d+=4 ); + + if (n == 2) { + l = dtoh32a( d+=4 ); + if (l != 0x10) { + ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l); + return 0; + } + d+=4; /* skip type */ + s2 = dtoh32a( d+=4 ); + c2 = dtoh32a( d+=4 ); + } + + *data = (unsigned char*) d+4; + + return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0); +} + +static inline uint32_t +ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value) +{ + uint32_t n = (value & 0xFF) ? 2 : 1; + uint32_t s = 4 + 0x10 * n; + + if( !data ) + return s; + + htod32a(data+=0, n); + htod32a(data+=4, 0x10); + htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1); + htod32a(data+=4, (value >> 12) & 0xF); + htod32a(data+=4, (value >> 8) & 0xF); + + if (n==2) { + htod32a(data+=4, 0x10); + htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1); + htod32a(data+=4, (value >> 4) & 0xF); + htod32a(data+=4, (value >> 0) & 0xF); + } + + return s; +} + /* PTP EOS Changes Entry unpack */ @@ -1255,22 +1341,38 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, ptp_debug (params, " %d: %02x", j, data[j]); break; } - if (propxcnt) { - ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.", - i, propxtype, proptype, dpd->DataType, propxcnt); - dpd->FormFlag = PTP_DPFF_Enumeration; - dpd->FORM.Enum.NumberOfValues = propxcnt; - dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt); + if (! propxcnt) + break; + ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.", + i, propxtype, proptype, dpd->DataType, propxcnt); + dpd->FormFlag = PTP_DPFF_Enumeration; + dpd->FORM.Enum.NumberOfValues = propxcnt; + dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt); + switch (proptype) { + case PTP_DPC_CANON_EOS_ImageFormat: + case PTP_DPC_CANON_EOS_ImageFormatCF: + case PTP_DPC_CANON_EOS_ImageFormatSD: + case PTP_DPC_CANON_EOS_ImageFormatExtHD: + /* special handling of ImageFormat properties */ + for (j=0;jFORM.Enum.SupportedValue[j].u16 = + dtoh16( ptp_unpack_EOS_ImageFormat( params, &data ) ); + ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16); + } + break; + default: + /* 'normal' enumerated types */ switch (dpd->DataType) { #define XX( TYPE, CONV )\ - for (j=0;jFORM.Enum.SupportedValue[j].TYPE = CONV(data); \ - ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(data)); \ - data += 4; /* might only be for propxtype 3 */ \ - } \ - break; + for (j=0;jFORM.Enum.SupportedValue[j].TYPE = CONV(data); \ + ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(data)); \ + data += 4; /* might only be for propxtype 3 */ \ + } \ + break; + case PTP_DTC_INT16: XX( i16, dtoh16a ); case PTP_DTC_UINT32: XX( u32, dtoh32a ); case PTP_DTC_UINT16: XX( u16, dtoh16a ); @@ -1498,6 +1600,20 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, /* debug is printed in switch above this one */ break; } + + /* ImageFormat special handling */ + switch (proptype) { + case PTP_DPC_CANON_EOS_ImageFormat: + case PTP_DPC_CANON_EOS_ImageFormatCF: + case PTP_DPC_CANON_EOS_ImageFormatSD: + case PTP_DPC_CANON_EOS_ImageFormatExtHD: + dpd->DataType = PTP_DTC_UINT16; + dpd->FactoryDefaultValue.u16 = ptp_unpack_EOS_ImageFormat( params, &data ); + dpd->CurrentValue.u16 = dpd->FactoryDefaultValue.u16; + ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8); + break; + } + break; } case 0: /* end marker */ diff --git a/camlibs/ptp2/ptp.c b/camlibs/ptp2/ptp.c index da549357d..a31bbeba1 100644 --- a/camlibs/ptp2/ptp.c +++ b/camlibs/ptp2/ptp.c @@ -2130,37 +2130,53 @@ ptp_canon_eos_setdevicepropvalue (PTPParams* params, break; if (params->nrofcanon_props == i) return PTP_RC_Undefined; - if (datatype != PTP_DTC_STR) { - data = calloc(sizeof(uint32_t),3); - size = sizeof(uint32_t)*3; - } else { - size = strlen(value->str) + 1 + 8; - data = calloc(sizeof(char),size); + + switch (propcode) { + case PTP_DPC_CANON_EOS_ImageFormat: + case PTP_DPC_CANON_EOS_ImageFormatCF: + case PTP_DPC_CANON_EOS_ImageFormatSD: + case PTP_DPC_CANON_EOS_ImageFormatExtHD: + /* special handling of ImageFormat properties */ + size = 8 + ptp_pack_EOS_ImageFormat( params, NULL, value->u16 ); + data = malloc( size ); + params->canon_props[i].dpd.CurrentValue.u16 = value->u16; + ptp_pack_EOS_ImageFormat( params, data + 8, value->u16 ); + break; + default: + if (datatype != PTP_DTC_STR) { + data = calloc(sizeof(uint32_t),3); + size = sizeof(uint32_t)*3; + } else { + size = strlen(value->str) + 1 + 8; + data = calloc(sizeof(char),size); + } + switch (datatype) { + case PTP_DTC_UINT8: + /*fprintf (stderr, "%x -> %d\n", propcode, value->u8);*/ + htod8a(&data[8], value->u8); + params->canon_props[i].dpd.CurrentValue.u8 = value->u8; + break; + case PTP_DTC_UINT16: + /*fprintf (stderr, "%x -> %d\n", propcode, value->u16);*/ + htod16a(&data[8], value->u16); + params->canon_props[i].dpd.CurrentValue.u16 = value->u16; + break; + case PTP_DTC_UINT32: + /*fprintf (stderr, "%x -> %d\n", propcode, value->u32);*/ + htod32a(&data[8], value->u32); + params->canon_props[i].dpd.CurrentValue.u32 = value->u32; + break; + case PTP_DTC_STR: + strcpy((char*)data + 8, value->str); + free (params->canon_props[i].dpd.CurrentValue.str); + params->canon_props[i].dpd.CurrentValue.str = strdup(value->str); + break; + } } + htod32a(&data[0], size); htod32a(&data[4], propcode); - switch (datatype) { - case PTP_DTC_UINT8: - /*fprintf (stderr, "%x -> %d\n", propcode, value->u8);*/ - htod8a(&data[8], value->u8); - params->canon_props[i].dpd.CurrentValue.u8 = value->u8; - break; - case PTP_DTC_UINT16: - /*fprintf (stderr, "%x -> %d\n", propcode, value->u16);*/ - htod16a(&data[8], value->u16); - params->canon_props[i].dpd.CurrentValue.u16 = value->u16; - break; - case PTP_DTC_UINT32: - /*fprintf (stderr, "%x -> %d\n", propcode, value->u32);*/ - htod32a(&data[8], value->u32); - params->canon_props[i].dpd.CurrentValue.u32 = value->u32; - break; - case PTP_DTC_STR: - strcpy((char*)data + 8, value->str); - free (params->canon_props[i].dpd.CurrentValue.str); - params->canon_props[i].dpd.CurrentValue.str = strdup(value->str); - break; - } + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); free (data); return ret;