--- libmtp-1.1.8/src/libmtp.c.orig 2017-07-08 15:24:05.362906649 -0400 +++ libmtp-1.1.8/src/libmtp.c 2017-07-08 15:25:19.804729041 -0400 @@ -1851,6 +1851,7 @@ LIBMTP_mtpdevice_t *LIBMTP_Open_Raw_Devi memset(current_params, 0, sizeof(PTPParams)); current_params->device_flags = rawdevice->device_entry.device_flags; current_params->nrofobjects = 0; + current_params->cachetime = 2; current_params->objects = NULL; current_params->response_packet_size = 0; current_params->response_packet = NULL; @@ -2420,6 +2421,8 @@ static void add_ptp_error_to_errorstack( uint16_t ptp_error, char const * const error_text) { + PTPParams *params = (PTPParams *) device->params; + if (device == NULL) { LIBMTP_ERROR("LIBMTP PANIC: Trying to add PTP error to a NULL device!\n"); return; @@ -2429,7 +2432,7 @@ static void add_ptp_error_to_errorstack( outstr[sizeof(outstr)-1] = '\0'; add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr); - snprintf(outstr, sizeof(outstr), "Error %04x: %s", ptp_error, ptp_strerror(ptp_error)); + snprintf(outstr, sizeof(outstr), "Error %04x: %s", ptp_error, ptp_strerror(ptp_error, params->deviceinfo.VendorExtensionID)); outstr[sizeof(outstr)-1] = '\0'; add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr); } @@ -3100,13 +3103,8 @@ void LIBMTP_Dump_Device_Info(LIBMTP_mtpd tmpext = tmpext->next; } printf("Supported operations:\n"); - for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) { - char txt[256]; - - (void) ptp_render_opcode(params, params->deviceinfo.OperationsSupported[i], - sizeof(txt), txt); - printf(" %04x: %s\n", params->deviceinfo.OperationsSupported[i], txt); - } + for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) + printf(" %04x: %s\n", params->deviceinfo.OperationsSupported[i], ptp_get_opcode_name(params, params->deviceinfo.OperationsSupported[i])); printf("Events supported:\n"); if (params->deviceinfo.EventsSupported_len == 0) { printf(" None.\n"); --- libmtp-1.1.8/src/ptp-pack.c.orig 2014-06-02 15:44:03.000000000 -0400 +++ libmtp-1.1.8/src/ptp-pack.c 2017-07-08 14:39:13.812876741 -0400 @@ -1,7 +1,7 @@ /* ptp-pack.c * * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl> - * Copyright (C) 2003-2012 Marcus Meissner <marcus@jet.franken.de> + * Copyright (C) 2003-2016 Marcus Meissner <marcus@jet.franken.de> * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se> * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com> * Copyright (C) 2009 Axel Waggershauser <awagger@web.de> @@ -30,7 +30,7 @@ #ifndef UINT_MAX # define UINT_MAX 0xFFFFFFFF #endif -#ifdef HAVE_ICONV +#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H) #include <iconv.h> #endif @@ -127,7 +127,7 @@ dtoh64ap (PTPParams *params, const unsig static inline char* -ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len) +ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t total, uint8_t *len) { uint8_t length; uint16_t string[PTP_MAXSTRLEN+1]; @@ -136,10 +136,16 @@ ptp_unpack_string(PTPParams *params, uns size_t nconv, srclen, destlen; char *src, *dest; + if (offset + 1 >= total) + return NULL; + length = dtoh8a(&data[offset]); /* PTP_MAXSTRLEN == 255, 8 bit len */ *len = length; if (length == 0) /* nothing to do? */ - return(NULL); + return NULL; + + if (offset + 1 + length*sizeof(string[0]) > total) + return NULL; /* copy to string[] to ensure correct alignment for iconv(3) */ memcpy(string, &data[offset+1], length * sizeof(string[0])); @@ -152,7 +158,7 @@ ptp_unpack_string(PTPParams *params, uns dest = loclstr; destlen = sizeof(loclstr)-1; nconv = (size_t)-1; -#ifdef HAVE_ICONV +#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H) if (params->cd_ucs2_to_locale != (iconv_t)-1) nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen); #endif @@ -193,7 +199,7 @@ ptp_pack_string(PTPParams *params, char /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */ memset(ucs2strp, 0, sizeof(ucs2str)); /* XXX: necessary? */ -#ifdef HAVE_ICONV +#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H) if (params->cd_locale_to_ucs2 != (iconv_t)-1) { size_t nconv; size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */ @@ -258,17 +264,34 @@ ptp_get_packed_stringcopy(PTPParams *par } static inline uint32_t -ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array) +ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint32_t **array) { uint32_t n, i=0; + if (!data) + return 0; + + if (offset >= datalen) + return 0; + + if (offset + sizeof(uint32_t) > datalen) + return 0; + *array = NULL; n=dtoh32a(&data[offset]); if (n >= UINT_MAX/sizeof(uint32_t)) return 0; if (!n) return 0; + + if (offset + sizeof(uint32_t)*(n+1) > datalen) { + ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)*(n+1) , datalen); + return 0; + } + *array = malloc (n*sizeof(uint32_t)); + if (!*array) + return 0; for (i=0;i<n;i++) (*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]); return n; @@ -280,6 +303,8 @@ ptp_pack_uint32_t_array(PTPParams *param uint32_t i=0; *data = malloc ((arraylen+1)*sizeof(uint32_t)); + if (!*data) + return 0; htod32a(&(*data)[0],arraylen); for (i=0;i<arraylen;i++) htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]); @@ -287,17 +312,27 @@ ptp_pack_uint32_t_array(PTPParams *param } static inline uint32_t -ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array) +ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint16_t **array) { uint32_t n, i=0; + if (!data) + return 0; *array = NULL; n=dtoh32a(&data[offset]); if (n >= UINT_MAX/sizeof(uint16_t)) return 0; if (!n) return 0; + if (offset + sizeof(uint32_t) > datalen) + return 0; + if (offset + sizeof(uint32_t)+sizeof(uint16_t)*n > datalen) { + ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)+n*sizeof(uint16_t) , datalen); + return 0; + } *array = malloc (n*sizeof(uint16_t)); + if (!*array) + return 0; for (i=0;i<n;i++) (*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]); return n; @@ -312,104 +347,130 @@ ptp_unpack_uint16_t_array(PTPParams *par #define PTP_di_FunctionalMode 8 #define PTP_di_OperationsSupported 10 -static inline void +static inline int ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen) { uint8_t len; unsigned int totallen; - if (!data) return; - if (datalen < 12) return; + if (!data) return 0; + if (datalen < 12) return 0; + memset (di, 0, sizeof(*di)); di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]); di->VendorExtensionID = dtoh32a(&data[PTP_di_VendorExtensionID]); di->VendorExtensionVersion = dtoh16a(&data[PTP_di_VendorExtensionVersion]); - di->VendorExtensionDesc = + di->VendorExtensionDesc = ptp_unpack_string(params, data, - PTP_di_VendorExtensionDesc, &len); + PTP_di_VendorExtensionDesc, + datalen, + &len); totallen=len*2+1; - di->FunctionalMode = + if (datalen <= totallen) return 0; + di->FunctionalMode = dtoh16a(&data[PTP_di_FunctionalMode+totallen]); di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data, PTP_di_OperationsSupported+totallen, + datalen, &di->OperationsSupported); totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t); + if (datalen <= totallen+PTP_di_OperationsSupported) return 0; di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data, PTP_di_OperationsSupported+totallen, + datalen, &di->EventsSupported); totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t); + if (datalen <= totallen+PTP_di_OperationsSupported) return 0; di->DevicePropertiesSupported_len = ptp_unpack_uint16_t_array(params, data, PTP_di_OperationsSupported+totallen, + datalen, &di->DevicePropertiesSupported); totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t); + if (datalen <= totallen+PTP_di_OperationsSupported) return 0; di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data, PTP_di_OperationsSupported+totallen, + datalen, &di->CaptureFormats); totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t); + if (datalen <= totallen+PTP_di_OperationsSupported) return 0; di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data, PTP_di_OperationsSupported+totallen, + datalen, &di->ImageFormats); totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t); + if (datalen <= totallen+PTP_di_OperationsSupported) return 0; di->Manufacturer = ptp_unpack_string(params, data, PTP_di_OperationsSupported+totallen, + datalen, &len); totallen+=len*2+1; + /* be more relaxed ... as these are optional its ok if they are not here */ + if (datalen <= totallen+PTP_di_OperationsSupported) return 1; di->Model = ptp_unpack_string(params, data, PTP_di_OperationsSupported+totallen, + datalen, &len); totallen+=len*2+1; + /* be more relaxed ... as these are optional its ok if they are not here */ + if (datalen <= totallen+PTP_di_OperationsSupported) return 1; di->DeviceVersion = ptp_unpack_string(params, data, PTP_di_OperationsSupported+totallen, + datalen, &len); totallen+=len*2+1; + /* be more relaxed ... as these are optional its ok if they are not here */ + if (datalen <= totallen+PTP_di_OperationsSupported) return 1; di->SerialNumber = ptp_unpack_string(params, data, PTP_di_OperationsSupported+totallen, + datalen, &len); + return 1; } inline static void ptp_free_DI (PTPDeviceInfo *di) { - if (di->SerialNumber) free (di->SerialNumber); - if (di->DeviceVersion) free (di->DeviceVersion); - if (di->Model) free (di->Model); - if (di->Manufacturer) free (di->Manufacturer); - if (di->ImageFormats) free (di->ImageFormats); - if (di->CaptureFormats) free (di->CaptureFormats); - if (di->VendorExtensionDesc) free (di->VendorExtensionDesc); - if (di->OperationsSupported) free (di->OperationsSupported); - if (di->EventsSupported) free (di->EventsSupported); - if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported); + free (di->SerialNumber); + free (di->DeviceVersion); + free (di->Model); + free (di->Manufacturer); + free (di->ImageFormats); + free (di->CaptureFormats); + free (di->VendorExtensionDesc); + free (di->OperationsSupported); + free (di->EventsSupported); + free (di->DevicePropertiesSupported); + memset(di, 0, sizeof(*di)); } /* EOS Device Info unpack */ -static inline void +static inline int ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen) { unsigned int totallen = 4; memset (di,0, sizeof(*di)); - if (datalen < 8) return; + if (datalen < 8) return 0; /* uint32_t struct len - ignore */ di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data, - totallen, &di->EventsSupported); - if (!di->EventsSupported) return; + totallen, datalen, &di->EventsSupported); + if (!di->EventsSupported) return 0; totallen += di->EventsSupported_len*sizeof(uint32_t)+4; - if (totallen >= datalen) return; + if (totallen >= datalen) return 0; di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data, - totallen, &di->DevicePropertiesSupported); - if (!di->DevicePropertiesSupported) return; + totallen, datalen, &di->DevicePropertiesSupported); + if (!di->DevicePropertiesSupported) return 0; totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4; - if (totallen >= datalen) return; + if (totallen >= datalen) return 0; di->unk_len = ptp_unpack_uint32_t_array(params, data, - totallen, &di->unk); - if (!di->unk) return; + totallen, datalen, &di->unk); + if (!di->unk) return 0; totallen += di->unk_len*sizeof(uint32_t)+4; - return; + return 1; } static inline void @@ -428,7 +489,7 @@ static inline void ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len) { if (len) { - oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler); + oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, len, &oh->Handler); } else { oh->n = 0; oh->Handler = NULL; @@ -442,13 +503,13 @@ ptp_unpack_OH (PTPParams *params, unsign static inline void ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len) { - if (!data || !len) { - sids->n = 0; - sids->Storage = NULL; + sids->n = 0; + sids->Storage = NULL; + + if (!data || !len) return; - } - sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, - &sids->Storage); + + sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, len, &sids->Storage); } /* StorageInfo pack/unpack */ @@ -461,22 +522,29 @@ ptp_unpack_SIDs (PTPParams *params, unsi #define PTP_si_FreeSpaceInImages 22 #define PTP_si_StorageDescription 26 -static inline void +static inline int ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len) { uint8_t storagedescriptionlen; + if (len < 26) return 0; si->StorageType=dtoh16a(&data[PTP_si_StorageType]); si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]); si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]); si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]); si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]); si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]); + + /* FIXME: check more lengths here */ si->StorageDescription=ptp_unpack_string(params, data, - PTP_si_StorageDescription, &storagedescriptionlen); + PTP_si_StorageDescription, + len, + &storagedescriptionlen); si->VolumeLabel=ptp_unpack_string(params, data, PTP_si_StorageDescription+storagedescriptionlen*2+1, + len, &storagedescriptionlen); + return 1; } /* ObjectInfo pack/unpack */ @@ -617,6 +685,12 @@ ptp_unpack_OI (PTPParams *params, unsign uint8_t capturedatelen; char *capture_date; + if (len < PTP_oi_SequenceNumber) + return; + + oi->Filename = oi->Keywords = NULL; + + /* FIXME: also handle length with all the strings at the end */ oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]); oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]); oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]); @@ -639,10 +713,10 @@ ptp_unpack_OI (PTPParams *params, unsign oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]); oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]); - oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen); + oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, len, &filenamelen); capture_date = ptp_unpack_string(params, data, - PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen); + PTP_oi_filenamelen+filenamelen*2+1, len, &capturedatelen); /* subset of ISO 8601, without '.s' tenths of second and * time zone */ @@ -652,7 +726,7 @@ ptp_unpack_OI (PTPParams *params, unsign /* now the modification date ... */ capture_date = ptp_unpack_string(params, data, PTP_oi_filenamelen+filenamelen*2 - +capturedatelen*2+2,&capturedatelen); + +capturedatelen*2+2, len, &capturedatelen); oi->ModificationDate = ptp_unpack_PTPTIME(capture_date); free(capture_date); } @@ -674,6 +748,8 @@ ptp_unpack_OI (PTPParams *params, unsign \ if (n >= UINT_MAX/sizeof(val->a.v[0])) \ return 0; \ + if (n > (total - (*offset))/sizeof(val->a.v[0]))\ + return 0; \ val->a.count = n; \ val->a.v = malloc(sizeof(val->a.v[0])*n); \ if (!val->a.v) return 0; \ @@ -683,9 +759,12 @@ ptp_unpack_OI (PTPParams *params, unsign static inline unsigned int ptp_unpack_DPV ( - PTPParams *params, unsigned char* data, unsigned int *offset, int total, + PTPParams *params, unsigned char* data, unsigned int *offset, unsigned int total, PTPPropertyValue* value, uint16_t datatype ) { + if (*offset >= total) /* we are at the end or over the end of the buffer */ + return 0; + switch (datatype) { case PTP_DTC_INT8: CTVAL(value->i8,dtoh8a); @@ -752,7 +831,11 @@ ptp_unpack_DPV ( case PTP_DTC_STR: { uint8_t len; /* XXX: max size */ - value->str = ptp_unpack_string(params,data,*offset,&len); + + if (*offset >= total+1) + return 0; + + value->str = ptp_unpack_string(params,data,*offset,total,&len); *offset += len*2+1; if (!value->str) return 1; @@ -776,6 +859,8 @@ ptp_unpack_DPD (PTPParams *params, unsig unsigned int offset = 0, ret; memset (dpd, 0, sizeof(*dpd)); + if (dpdlen <= 5) + return 0; dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]); dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]); dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]); @@ -854,13 +939,19 @@ static inline int ptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset) { unsigned int ret; +#if 0 + unsigned int unk1, unk2; +#endif memset (dpd, 0, sizeof(*dpd)); dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]); dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]); #if 0 - dpd->GetSet=dtoh8a(&data[PTP_dpd_Sony_GetSet]); + /* get set ? */ + unk1 = dtoh8a(&data[PTP_dpd_Sony_GetSet]); + unk2 = dtoh8a(&data[PTP_dpd_Sony_Unknown]); + ptp_debug (params, "prop 0x%04x, datatype 0x%04x, unk1 %d unk2 %d", dpd->DevicePropertyCode, dpd->DataType, unk1, unk2); #endif dpd->GetSet=1; @@ -1251,8 +1342,11 @@ ptp_unpack_OPL (PTPParams *params, unsig MTPProperties *props = NULL; unsigned int offset = 0, i; - if (prop_count == 0) { - *pprops = NULL; + *pprops = NULL; + if (prop_count == 0) + return 0; + if (prop_count >= INT_MAX/sizeof(MTPProperties)) { + ptp_debug (params ,"prop_count %d is too large", prop_count); return 0; } ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count); @@ -1263,7 +1357,7 @@ ptp_unpack_OPL (PTPParams *params, unsig for (i = 0; i < prop_count; i++) { if (len <= 0) { ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count); - ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i); + ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL"); ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i); qsort (props, i, sizeof(MTPProperties),_compare_func); *pprops = props; @@ -1282,7 +1376,12 @@ ptp_unpack_OPL (PTPParams *params, unsig len -= sizeof(uint16_t); offset = 0; - ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype); + if (!ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype)) { + ptp_debug (params ,"unpacking DPV of property %d encountered insufficient buffer. attack?", i); + qsort (props, i, sizeof(MTPProperties),_compare_func); + *pprops = props; + return i; + } data += offset; len -= offset; } @@ -1409,7 +1508,8 @@ ObjectInfo for 'IMG_0199.JPG': 0014 72 0c 74 92 OID 0018 01 00 02 00 StorageID 001c 01 38 00 00 OFC -0020 00 00 00 00 00 00 00 00 ? +0020 00 00 00 00 ?? +0024 21 00 00 00 flags (4 bytes? 1 byte?) 0028 19 d5 21 00 Size 002c 00 00 74 92 ? 0030 70 0c 74 92 OID @@ -1422,7 +1522,7 @@ ObjectInfo for 'IMG_0199.JPG': #define PTP_cefe_ObjectHandle 0 #define PTP_cefe_StorageID 4 #define PTP_cefe_ObjectFormatCode 8 -#define PTP_cefe_Flags 12 +#define PTP_cefe_Flags 16 #define PTP_cefe_ObjectSize 20 #define PTP_cefe_Filename 32 #define PTP_cefe_Time 48 @@ -1541,19 +1641,125 @@ ptp_pack_EOS_ImageFormat (PTPParams* par return s; } +/* 00: 32 bit size + * 04: 16 bit subsize + * 08: 16 bit version (?) + * 0c: 16 bit focus_points_in_struct + * 10: 16 bit focus_points_in_use + * 14: variable arrays: + * 16 bit sizex, 16 bit sizey + * 16 bit othersizex, 16 bit othersizey + * 16 bit array height[focus_points_in_struct] + * 16 bit array width[focus_points_in_struct] + * 16 bit array offsetheight[focus_points_in_struct] middle is 0 + * 16 bit array offsetwidth[focus_points_in_struct] middle is ? + * bitfield of selected focus points, starting with 0 [size focus_points_in_struct in bits] + * unknown stuff , likely which are active + * 16 bit 0xffff + * + * size=NxN,size2=NxN,points={NxNxNxN,NxNxNxN,...},selected={0,1,2} + */ +static inline char* +ptp_unpack_EOS_FocusInfoEx (PTPParams* params, unsigned char** data, uint32_t datasize ) +{ + uint32_t size = dtoh32a( *data ); + uint32_t halfsize = dtoh16a( (*data) + 4); + uint32_t version = dtoh16a( (*data) + 6); + uint32_t focus_points_in_struct = dtoh16a( (*data) + 8); + uint32_t focus_points_in_use = dtoh16a( (*data) + 10); + uint32_t sizeX = dtoh16a( (*data) + 12); + uint32_t sizeY = dtoh16a( (*data) + 14); + uint32_t size2X = dtoh16a( (*data) + 16); + uint32_t size2Y = dtoh16a( (*data) + 18); + uint32_t i; + uint32_t maxlen; + char *str, *p; + + if ((size >= datasize) || (size < 20)) + return strdup("bad size 1"); + /* every focuspoint gets 4 (16 bit number possible "-" sign and a x) and a ,*/ + /* inital things around lets say 100 chars at most. + * FIXME: check selected when we decode it + */ + if (size < focus_points_in_struct*8) { + ptp_error(params, "focus_points_in_struct %d is too large vs size %d", focus_points_in_struct, size); + return strdup("bad size 2"); + } + if (focus_points_in_use > focus_points_in_struct) { + ptp_error(params, "focus_points_in_use %d is larger than focus_points_in_struct %d", focus_points_in_use, focus_points_in_struct); + return strdup("bad size 3"); + } + + maxlen = focus_points_in_use*32 + 100 + (size - focus_points_in_struct*8)*2; + if (halfsize != size-4) { + ptp_error(params, "halfsize %d is not expected %d", halfsize, size-4); + return strdup("bad size 4"); + } + if (20 + focus_points_in_struct*8 + (focus_points_in_struct+7)/8 > size) { + ptp_error(params, "size %d is too large for fp in struct %d", focus_points_in_struct*8 + 20 + (focus_points_in_struct+7)/8, size); + return strdup("bad size 5"); + } +#if 0 + ptp_debug(params,"d1d3 content:"); + for (i=0;i<size;i+=2) + ptp_debug(params,"%d: %02x %02x", i, (*data)[i], (*data)[i+1]); +#endif + ptp_debug(params,"d1d3 version %d", version); + ptp_debug(params,"d1d3 size %d", size); + ptp_debug(params,"d1d3 focus points in struct %d, in use %d", focus_points_in_struct, focus_points_in_use); + + str = (char*)malloc( maxlen ); + if (!str) + return NULL; + p = str; + + p += sprintf(p,"eosversion=%d,size=%dx%d,size2=%dx%d,points={", version, sizeX, sizeY, size2X, size2Y); + for (i=0;i<focus_points_in_use;i++) { + int16_t x = dtoh16a((*data) + focus_points_in_struct*4 + 20 + 2*i); + int16_t y = dtoh16a((*data) + focus_points_in_struct*6 + 20 + 2*i); + int16_t w = dtoh16a((*data) + focus_points_in_struct*2 + 20 + 2*i); + int16_t h = dtoh16a((*data) + focus_points_in_struct*0 + 20 + 2*i); + + p += sprintf(p,"{%d,%d,%d,%d}",x,y,w,h); + + if (i<focus_points_in_use-1) + p += sprintf(p,","); + } + p += sprintf(p,"},select={"); + for (i=0;i<focus_points_in_use;i++) { + if ((1<<(i%8)) & ((*data)[focus_points_in_struct*8+20+i/8])) + p+=sprintf(p,"%d,", i); + } + + p += sprintf(p,"},unknown={"); + for (i=focus_points_in_struct*8+(focus_points_in_struct+7)/8+20;i<size;i++) { + if ((p-str) > maxlen - 4) + break; + p+=sprintf(p,"%02x", (*data)[i]); + } + p += sprintf(p,"}"); + return str; +} + + static inline char* ptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data ) { uint32_t s = dtoh32a( *data ); uint32_t n = s/4, i; - char* str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/ + char *str, *p; + + if (s > 1024) { + ptp_debug (params, "customfuncex data is larger than 1k / %d... unexpected?", s); + return strdup("bad length"); + } + str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/ if (!str) - return str; - char* p = str; + return strdup("malloc failed"); + p = str; for (i=0; i < n; ++i) p += sprintf(p, "%x,", dtoh32a( *data + 4*i )); - return str; } @@ -1602,6 +1808,44 @@ ptp_pack_EOS_CustomFuncEx (PTPParams* pa #define PTP_ece_OA_Parent 0x20 #define PTP_ece_OA_Name 0x28 +#define PTP_ece2_OA_ObjectID 8 /* OK */ +#define PTP_ece2_OA_StorageID 0x0c /* OK */ +#define PTP_ece2_OA_OFC 0x10 /* OK */ +#define PTP_ece2_OA_Size 0x1c /* OK, might be 64 bit now? */ +#define PTP_ece2_OA_Parent 0x24 +#define PTP_ece2_OA_2ndOID 0x28 +#define PTP_ece2_OA_Name 0x2c /* OK */ + +/* for PTP_EC_CANON_EOS_ObjectAddedNew */ +#define PTP_ece_OAN_OFC 0x0c +#define PTP_ece_OAN_Size 0x14 + +static PTPDevicePropDesc* +_lookup_or_allocate_canon_prop(PTPParams *params, uint16_t proptype) +{ + unsigned int j; + + for (j=0;j<params->nrofcanon_props;j++) + if (params->canon_props[j].proptype == proptype) + break; + if (j<params->nrofcanon_props) + return ¶ms->canon_props[j].dpd; + + if (j) + params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1)); + else + params->canon_props = malloc(sizeof(params->canon_props[0])); + params->canon_props[j].proptype = proptype; + params->canon_props[j].size = 0; + params->canon_props[j].data = NULL; + memset (¶ms->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd)); + params->canon_props[j].dpd.GetSet = 1; + params->canon_props[j].dpd.FormFlag = PTP_DPFF_None; + params->nrofcanon_props = j+1; + return ¶ms->canon_props[j].dpd; +} + + static inline int ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce) { @@ -1611,18 +1855,33 @@ ptp_unpack_CANON_changes (PTPParams *par if (data==NULL) return 0; - while (curdata - data < datasize) { + while (curdata - data + 8 < datasize) { uint32_t size = dtoh32a(&curdata[PTP_ece_Size]); uint32_t type = dtoh32a(&curdata[PTP_ece_Type]); + if (size > datasize) { + ptp_debug (params, "size %d is larger than datasize %d", size, datasize); + break; + } + if (size < 8) { + ptp_debug (params, "size %d is smaller than 8.", size); + break; + } if ((size == 8) && (type == 0)) break; + if ((curdata - data) + size >= datasize) { + ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries"); + break; + } if (type == PTP_EC_CANON_EOS_OLCInfoChanged) { unsigned int j; - for (j=0;j<31;j++) - if (dtoh32a(curdata+12) & (1<<j)) - entries++; + entries++; + if (size >= 12+2) { + for (j=0;j<31;j++) + if (dtoh16a(curdata+12) & (1<<j)) + entries++; + } } curdata += size; entries++; @@ -1631,35 +1890,75 @@ ptp_unpack_CANON_changes (PTPParams *par if (!ce) return 0; curdata = data; - while (curdata - data < datasize) { + while (curdata - data + 8 < datasize) { uint32_t size = dtoh32a(&curdata[PTP_ece_Size]); uint32_t type = dtoh32a(&curdata[PTP_ece_Type]); + if (size > datasize) { + ptp_debug (params, "size %d is larger than datasize %d", size, datasize); + break; + } + if (size < 8) { + ptp_debug (params, "size %d is smaller than 8", size); + break; + } + + if ((size == 8) && (type == 0)) + break; + + if ((curdata - data) + size >= datasize) { + ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries"); + break; + } + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; ce[i].u.info = NULL; switch (type) { - case PTP_EC_CANON_EOS_ObjectAddedEx: + case PTP_EC_CANON_EOS_ObjectAddedEx: + if (size < PTP_ece_OA_Name+1) { + ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OA_Name+1); + break; + } ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO; ce[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OA_ObjectID]); - ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece_OA_StorageID]); + ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece_OA_StorageID]); ce[i].u.object.oi.ParentObject = dtoh32a(&curdata[PTP_ece_OA_Parent]); ce[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OA_OFC]); ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]); - ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OA_Name])); + ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OA_Name])); + ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename); + break; + case PTP_EC_CANON_EOS_ObjectAddedUnknown: /* FIXME: review if the data used is correct */ + if (size < PTP_ece2_OA_Name+1) { + ptp_debug (params, "size %d is smaller than %d", size, PTP_ece2_OA_Name+1); + break; + } + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO; + ce[i].u.object.oid = dtoh32a(&curdata[PTP_ece2_OA_ObjectID]); + ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece2_OA_StorageID]); + ce[i].u.object.oi.ParentObject = dtoh32a(&curdata[PTP_ece2_OA_Parent]); + ce[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece2_OA_OFC]); + ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece2_OA_Size]); /* FIXME: might be 64bit now */ + ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece2_OA_Name])); ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename); break; - case PTP_EC_CANON_EOS_RequestObjectTransfer: + case PTP_EC_CANON_EOS_RequestObjectTransfer: + case PTP_EC_CANON_EOS_RequestObjectTransferNew: /* FIXME: confirm */ + if (size < PTP_ece_OI_Name+1) { + ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OI_Name+1); + break; + } ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER; ce[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OI_ObjectID]); - ce[i].u.object.oi.StorageID = 0; /* use as marker */ + ce[i].u.object.oi.StorageID = 0; /* use as marker */ ce[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OI_OFC]); ce[i].u.object.oi.ParentObject = 0; /* check, but use as marker */ ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]); - ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OI_Name])); + ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OI_Name])); ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %p", i, ce[i].u.object.oid, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename); break; - case PTP_EC_CANON_EOS_AvailListChanged: { /* property desc */ + case PTP_EC_CANON_EOS_AvailListChanged: { /* property desc */ uint32_t proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]); uint32_t propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]); uint32_t propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]); @@ -1667,6 +1966,11 @@ ptp_unpack_CANON_changes (PTPParams *par unsigned int j; PTPDevicePropDesc *dpd; + if (size < PTP_ece_Prop_Desc_Data) { + ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Desc_Data); + break; + } + ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype); for (j=0;j<params->nrofcanon_props;j++) if (params->canon_props[j].proptype == proptype) @@ -1681,7 +1985,7 @@ ptp_unpack_CANON_changes (PTPParams *par * 7 - string? */ if (propxtype != 3) { - ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype); + ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled, size %d", i, propxtype, proptype, size); for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++) ptp_debug (params, " %d: %02x", j, xdata[j]); break; @@ -1695,7 +1999,7 @@ ptp_unpack_CANON_changes (PTPParams *par i, propxtype, proptype, dpd->DataType, propxcnt); dpd->FormFlag = PTP_DPFF_Enumeration; dpd->FORM.Enum.NumberOfValues = propxcnt; - if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue); + free (dpd->FORM.Enum.SupportedValue); dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt); switch (proptype) { @@ -1714,8 +2018,12 @@ ptp_unpack_CANON_changes (PTPParams *par /* 'normal' enumerated types */ switch (dpd->DataType) { #define XX( TYPE, CONV )\ - for (j=0;j<propxcnt;j++) { \ - dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \ + if (sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data > size) { \ + ptp_debug (params, "size %d does not match needed %d", sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data, size); \ + break; \ + } \ + for (j=0;j<propxcnt;j++) { \ + dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \ ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \ xdata += 4; /* might only be for propxtype 3 */ \ } \ @@ -1727,7 +2035,10 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_DTC_UINT8: XX( u8, dtoh8a ); #undef XX default: - ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata)); + free (dpd->FORM.Enum.SupportedValue); + dpd->FORM.Enum.SupportedValue = NULL; + dpd->FORM.Enum.NumberOfValues = 0; + ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, size %d, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata), size); for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */ ptp_debug (params, " %3d: 0x%8x", j, dtoh32a(xdata)); break; @@ -1742,6 +2053,10 @@ ptp_unpack_CANON_changes (PTPParams *par unsigned char *xdata = &curdata[PTP_ece_Prop_Val_Data]; PTPDevicePropDesc *dpd; + if (size < PTP_ece_Prop_Val_Data) { + ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Val_Data); + break; + } ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data); for (j=0;j<params->nrofcanon_props;j++) if (params->canon_props[j].proptype == proptype) @@ -1750,6 +2065,7 @@ ptp_unpack_CANON_changes (PTPParams *par if ( (params->canon_props[j].size != size) || (memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) { params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data); + params->canon_props[j].size = size; memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data); } } else { @@ -1757,7 +2073,6 @@ ptp_unpack_CANON_changes (PTPParams *par params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1)); else params->canon_props = malloc(sizeof(params->canon_props[0])); - params->canon_props[j].type = type; params->canon_props[j].proptype = proptype; params->canon_props[j].size = size; params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data); @@ -1823,6 +2138,9 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_DPC_CANON_EOS_ModelID: case PTP_DPC_CANON_EOS_LensID: case PTP_DPC_CANON_EOS_StroboFiring: + case PTP_DPC_CANON_EOS_AFSelectFocusArea: + case PTP_DPC_CANON_EOS_ContinousAFMode: + case PTP_DPC_CANON_EOS_MirrorUpSetting: dpd->DataType = PTP_DTC_UINT32; break; /* enumeration for AEM is never provided, but is available to set */ @@ -1846,12 +2164,13 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_DPC_CANON_EOS_EVFMode: case PTP_DPC_CANON_EOS_EVFOutputDevice: case PTP_DPC_CANON_EOS_AutoPowerOff: + case PTP_DPC_CANON_EOS_EVFRecordStatus: dpd->DataType = PTP_DTC_UINT16; break; case PTP_DPC_CANON_EOS_PictureStyle: case PTP_DPC_CANON_EOS_WhiteBalance: case PTP_DPC_CANON_EOS_MeteringMode: - case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */ + case PTP_DPC_CANON_EOS_ExpCompensation: dpd->DataType = PTP_DTC_UINT8; break; case PTP_DPC_CANON_EOS_Owner: @@ -1902,7 +2221,6 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_DPC_CANON_EOS_EVFWBMode: case PTP_DPC_CANON_EOS_EVFClickWBCoeffs: case PTP_DPC_CANON_EOS_EVFColorTemp: - case PTP_DPC_CANON_EOS_EVFRecordStatus: case PTP_DPC_CANON_EOS_ExposureSimMode: case PTP_DPC_CANON_EOS_LvAfSystem: case PTP_DPC_CANON_EOS_MovSize: @@ -1915,7 +2233,7 @@ ptp_unpack_CANON_changes (PTPParams *par if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0) ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) ); for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++) - ptp_debug (params, " %d: 0x%8x", j, ((uint32_t*)xdata)[j]); + ptp_debug (params, " %d: 0x%8x", j, dtoh32a(xdata+j*4)); break; /* ImageFormat properties have to be ignored here, see special handling below */ case PTP_DPC_CANON_EOS_ImageFormat: @@ -1923,6 +2241,7 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_DPC_CANON_EOS_ImageFormatSD: case PTP_DPC_CANON_EOS_ImageFormatExtHD: case PTP_DPC_CANON_EOS_CustomFuncEx: + case PTP_DPC_CANON_EOS_FocusInfoEx: break; default: ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data); @@ -1951,16 +2270,21 @@ ptp_unpack_CANON_changes (PTPParams *par dpd->CurrentValue.u8 = dtoh8a(xdata); ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8); break; + case PTP_DTC_INT8: + dpd->FactoryDefaultValue.i8 = dtoh8a(xdata); + dpd->CurrentValue.i8 = dtoh8a(xdata); + ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.i8); + break; case PTP_DTC_STR: { #if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */ uint8_t len = 0; dpd->FactoryDefaultValue.str = ptp_unpack_string(params, data, 0, &len); dpd->CurrentValue.str = ptp_unpack_string(params, data, 0, &len); #else - if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str); + free (dpd->FactoryDefaultValue.str); dpd->FactoryDefaultValue.str = strdup( (char*)xdata ); - if (dpd->CurrentValue.str) free (dpd->CurrentValue.str); + free (dpd->CurrentValue.str); dpd->CurrentValue.str = strdup( (char*)xdata ); #endif ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str); @@ -1984,12 +2308,20 @@ ptp_unpack_CANON_changes (PTPParams *par break; case PTP_DPC_CANON_EOS_CustomFuncEx: dpd->DataType = PTP_DTC_STR; - if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str); - if (dpd->CurrentValue.str) free (dpd->CurrentValue.str); - dpd->FactoryDefaultValue.str = ptp_unpack_EOS_CustomFuncEx( params, &data ); + free (dpd->FactoryDefaultValue.str); + free (dpd->CurrentValue.str); + dpd->FactoryDefaultValue.str = ptp_unpack_EOS_CustomFuncEx( params, &xdata ); dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str ); ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str); break; + case PTP_DPC_CANON_EOS_FocusInfoEx: + dpd->DataType = PTP_DTC_STR; + free (dpd->FactoryDefaultValue.str); + free (dpd->CurrentValue.str); + dpd->FactoryDefaultValue.str = ptp_unpack_EOS_FocusInfoEx( params, &xdata, size ); + dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str ); + ptp_debug (params,"event %d: decoded focus info, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str); + break; } break; @@ -1998,23 +2330,29 @@ ptp_unpack_CANON_changes (PTPParams *par case PTP_EC_CANON_EOS_OLCInfoChanged: { uint32_t len, curoff; uint16_t mask,proptype; - unsigned int j; PTPDevicePropDesc *dpd; /* unclear what OLC stands for */ ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size); if (size >= 0x8) { /* event info */ - unsigned int j; - for (j=8;j<size;j++) - ptp_debug (params, " %d: %02x", j-8, curdata[j]); + unsigned int k; + for (k=8;k<size;k++) + ptp_debug (params, " %d: %02x", k-8, curdata[k]); } len = dtoh32a(curdata+8); - if (len != size-8) { + if ((len != size-8) && (len != size-4)) { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; - ptp_debug (params, "event %d: size %d, len %d", i, size, len); + ce[i].u.info = strdup("OLC size unexpected"); + ptp_debug (params, "event %d: OLC unexpected size %d for blob len %d (not -4 nor -8)", i, size, len); break; } mask = dtoh16a(curdata+8+4); + if (size < 14) { + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; + ce[i].u.info = strdup("OLC size too small"); + ptp_debug (params, "event %d: OLC unexpected size %d", i, size); + break; + } curoff = 8+4+4; if (mask & CANON_EOS_OLC_BUTTON) { ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; @@ -2028,13 +2366,7 @@ ptp_unpack_CANON_changes (PTPParams *par /* 6 bytes: 01 01 98 10 00 60 */ /* this seesm to be the shutter speed record */ proptype = PTP_DPC_CANON_EOS_ShutterSpeed; - for (j=0;j<params->nrofcanon_props;j++) - if (params->canon_props[j].proptype == proptype) - break; - if (j == params->nrofcanon_props) - ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i); - - dpd = ¶ms->canon_props[j].dpd; + dpd = _lookup_or_allocate_canon_prop(params, proptype); dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; @@ -2046,13 +2378,7 @@ ptp_unpack_CANON_changes (PTPParams *par /* 5 bytes: 01 01 5b 30 30 */ /* this seesm to be the aperture record */ proptype = PTP_DPC_CANON_EOS_Aperture; - for (j=0;j<params->nrofcanon_props;j++) - if (params->canon_props[j].proptype == proptype) - break; - if (j == params->nrofcanon_props) - ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i); - - dpd = ¶ms->canon_props[j].dpd; + dpd = _lookup_or_allocate_canon_prop(params, proptype); dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; @@ -2064,13 +2390,7 @@ ptp_unpack_CANON_changes (PTPParams *par /* 5 bytes: 01 01 00 78 */ /* this seesm to be the aperture record */ proptype = PTP_DPC_CANON_EOS_ISOSpeed; - for (j=0;j<params->nrofcanon_props;j++) - if (params->canon_props[j].proptype == proptype) - break; - if (j == params->nrofcanon_props) - ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i); - - dpd = ¶ms->canon_props[j].dpd; + dpd = _lookup_or_allocate_canon_prop(params, proptype); dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY; @@ -2107,13 +2427,15 @@ ptp_unpack_CANON_changes (PTPParams *par i++; } if (mask & 0x0040) { + int value = (signed char)curdata[curoff+2]; /* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */ + /* exposure indicator */ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; - ce[i].u.info = malloc(strlen("OLCInfo event 0x0040 content 0123456789abcd")+1); - sprintf(ce[i].u.info,"OLCInfo event 0x0040 content %02x%02x%02x%02x%02x%02x%02x", + ce[i].u.info = malloc(strlen("OLCInfo exposure indicator 012345678901234567890123456789abcd")+1); + sprintf(ce[i].u.info,"OLCInfo exposure indicator %d,%d,%d.%d (%02x%02x%02x%02x)", curdata[curoff], curdata[curoff+1], - curdata[curoff+2], + value/10,abs(value)%10, curdata[curoff+3], curdata[curoff+4], curdata[curoff+5], @@ -2137,9 +2459,9 @@ ptp_unpack_CANON_changes (PTPParams *par } if (mask & 0x0100) { /* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */ - ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; - ce[i].u.info = malloc(strlen("OLCInfo event 0x0100 content 0123456789ab")+1); - sprintf(ce[i].u.info,"OLCInfo event 0x0100 content %02x%02x%02x%02x%02x%02x", + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO; + ce[i].u.info = malloc(strlen("0123456789ab")+1); + sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x", curdata[curoff], curdata[curoff+1], curdata[curoff+2], @@ -2152,9 +2474,9 @@ ptp_unpack_CANON_changes (PTPParams *par } if (mask & 0x0200) { /* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */ - ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; - ce[i].u.info = malloc(strlen("OLCInfo event 0x0200 content 0123456789abcd")+1); - sprintf(ce[i].u.info,"OLCInfo event 0x0200 content %02x%02x%02x%02x%02x%02x%02x", + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK; + ce[i].u.info = malloc(strlen("0123456789abcd0123456789abcdef")+1); + sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x%02x", curdata[curoff], curdata[curoff+1], curdata[curoff+2], @@ -2229,9 +2551,13 @@ ptp_unpack_CANON_changes (PTPParams *par break; case PTP_EC_CANON_EOS_BulbExposureTime: ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN; - ce[i].u.info = malloc(strlen("BulbExposureTime 123456789")); + ce[i].u.info = malloc(strlen("BulbExposureTime 123456789012345678")); sprintf (ce[i].u.info, "BulbExposureTime %d", dtoh32a(curdata+8)); break; + case PTP_EC_CANON_EOS_ObjectRemoved: + ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED; + ce[i].u.object.oid = dtoh32a(curdata+8); + break; default: switch (type) { #define XX(x) case PTP_EC_CANON_EOS_##x: \ @@ -2240,7 +2566,6 @@ ptp_unpack_CANON_changes (PTPParams *par sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %d)", size); \ break; XX(RequestGetEvent) - XX(ObjectRemoved) XX(RequestGetObjectInfoEx) XX(StorageStatusChanged) XX(StorageInfoChanged) @@ -2264,6 +2589,7 @@ ptp_unpack_CANON_changes (PTPParams *par } if (size >= 0x8) { /* event info */ unsigned int j; + /*ptp_debug (params, "data=%p, curdata=%p, datsize=%d, size=%d", data, curdata, datasize, size);*/ for (j=8;j<size;j++) ptp_debug (params, " %d: %02x", j, curdata[j]); } @@ -2271,9 +2597,10 @@ ptp_unpack_CANON_changes (PTPParams *par break; } curdata += size; - if ((size == 8) && (type == 0)) - break; i++; + if (i >= entries) { + ptp_debug (params, "BAD: i %d, entries %d", i, entries); + } } if (!i) { free (ce); @@ -2301,8 +2628,10 @@ ptp_unpack_Nikon_EC (PTPParams *params, if (len < PTP_nikon_ec_Code) return; *cnt = dtoh16a(&data[PTP_nikon_ec_Length]); - if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */ + if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) { /* broken cnt? */ + *cnt = 0; return; + } if (!*cnt) return; @@ -2397,11 +2726,11 @@ ptp_unpack_canon_directory ( for (i=0;i<cnt;i++) if (ISOBJECT(dir+i*0x4c)) nrofobs++; handles->n = nrofobs; - handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs); + handles->Handler = calloc(nrofobs,sizeof(handles->Handler[0])); if (!handles->Handler) return PTP_RC_GeneralError; - *oinfos = calloc(sizeof((*oinfos)[0]),nrofobs); + *oinfos = calloc(nrofobs,sizeof((*oinfos)[0])); if (!*oinfos) return PTP_RC_GeneralError; - *flags = calloc(sizeof((*flags)[0]),nrofobs); + *flags = calloc(nrofobs,sizeof((*flags)[0])); if (!*flags) return PTP_RC_GeneralError; /* Migrate data into objects ids, handles into --- libmtp-1.1.8/src/ptp.c.orig 2014-06-02 15:44:03.000000000 -0400 +++ libmtp-1.1.8/src/ptp.c 2017-07-08 14:39:19.240864345 -0400 @@ -1,7 +1,7 @@ /* ptp.c * * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl> - * Copyright (C) 2003-2012 Marcus Meissner <marcus@jet.franken.de> + * Copyright (C) 2003-2016 Marcus Meissner <marcus@jet.franken.de> * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se> * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com> * Copyright (C) 2009 Axel Waggershauser <awagger@web.de> @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -#define _BSD_SOURCE +#define _DEFAULT_SOURCE #include "config.h" #include "ptp.h" @@ -34,7 +34,9 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> -#include <unistd.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif #ifdef ENABLE_NLS # include <libintl.h> @@ -55,9 +57,29 @@ # define N_(String) (String) #endif -#define CHECK_PTP_RC(result) {uint16_t r=(result); if (r!=PTP_RC_OK) return r;} +#define CHECK_PTP_RC(RESULT) do { uint16_t r = (RESULT); if (r != PTP_RC_OK) return r; } while(0) + +static inline void +ptp_init_container(PTPContainer* ptp, uint16_t code, int n_param, ...) +{ + va_list args; + int i; + + memset(ptp, 0, sizeof(*ptp)); + ptp->Code = code; + ptp->Nparam = n_param; + + va_start(args, n_param); + for (i=0; i<n_param; ++i) + (&ptp->Param1)[i] = va_arg(args, uint32_t); + va_end(args); +} + +#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N +#define NARGS(...) NARGS_SEQ(-1, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) -#define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));} +#define PTP_CNT_INIT(PTP, CODE, ...) \ + ptp_init_container(&PTP, CODE, NARGS(__VA_ARGS__), ##__VA_ARGS__) static uint16_t ptp_exit_recv_memory_handler (PTPDataHandler*,unsigned char**,unsigned long*); static uint16_t ptp_init_recv_memory_handler(PTPDataHandler*); @@ -104,12 +126,6 @@ ptp_error (PTPParams *params, const char /* major PTP functions */ -/* Transaction data phase description */ -#define PTP_DP_NODATA 0x0000 /* no data phase */ -#define PTP_DP_SENDDATA 0x0001 /* sending data */ -#define PTP_DP_GETDATA 0x0002 /* receiving data */ -#define PTP_DP_DATA_MASK 0x00ff /* data phase mask */ - /** * ptp_transaction: * params: PTPParams* @@ -153,36 +169,23 @@ ptp_transaction_new (PTPParams* params, ptp->Transaction_ID=params->transaction_id++; ptp->SessionID=params->session_id; /* send request */ - CHECK_PTP_RC(params->sendreq_func (params, ptp)); + CHECK_PTP_RC(params->sendreq_func (params, ptp, flags)); /* is there a dataphase? */ switch (flags&PTP_DP_DATA_MASK) { case PTP_DP_SENDDATA: { - uint16_t ret; - ret = params->senddata_func(params, ptp, - sendlen, handler); - if (ret == PTP_ERROR_CANCEL) { - ret = params->cancelreq_func(params, - params->transaction_id-1); - if (ret == PTP_RC_OK) - ret = PTP_ERROR_CANCEL; - } - if (ret != PTP_RC_OK) - return ret; + uint16_t ret = params->senddata_func(params, ptp, sendlen, handler); + if (ret == PTP_ERROR_CANCEL) + CHECK_PTP_RC(params->cancelreq_func(params, params->transaction_id-1)); + CHECK_PTP_RC(ret); } break; case PTP_DP_GETDATA: { - uint16_t ret; - ret = params->getdata_func(params, ptp, handler); - if (ret == PTP_ERROR_CANCEL) { - ret = params->cancelreq_func(params, - params->transaction_id-1); - if (ret == PTP_RC_OK) - ret = PTP_ERROR_CANCEL; - } - if (ret != PTP_RC_OK) - return ret; + uint16_t ret = params->getdata_func(params, ptp, handler); + if (ret == PTP_ERROR_CANCEL) + CHECK_PTP_RC(params->cancelreq_func(params, params->transaction_id-1)); + CHECK_PTP_RC(ret); } break; case PTP_DP_NODATA: @@ -200,10 +203,12 @@ ptp_transaction_new (PTPParams* params, tries++; continue; } - if (ret != PTP_RC_OK) - return ret; - + CHECK_PTP_RC(ret); + if (ptp->Transaction_ID < params->transaction_id-1) { + /* The Leica uses Transaction ID 0 on result from CloseSession. */ + if (cmd == PTP_OC_CloseSession) + break; tries++; ptp_debug (params, "PTP: Sequence number mismatch %d vs expected %d, suspecting old reply.", @@ -219,7 +224,9 @@ ptp_transaction_new (PTPParams* params, "PTP: Sequence number mismatch %d vs expected %d.", ptp->Transaction_ID, params->transaction_id-1 ); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION return PTP_ERROR_BADPARAM; +#endif } break; } @@ -305,7 +311,8 @@ ptp_init_send_memory_handler(PTPDataHand /* free private struct + data */ static uint16_t -ptp_exit_send_memory_handler (PTPDataHandler *handler) { +ptp_exit_send_memory_handler (PTPDataHandler *handler) +{ PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv; /* data is owned by caller */ free (priv); @@ -350,7 +357,7 @@ fd_putfunc(PTPParams* params, void* private, unsigned long sendlen, unsigned char *data, unsigned long *putlen ) { - int written; + ssize_t written; PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private; written = write (priv->fd, data, sendlen); @@ -357,7 +364,7 @@ fd_putfunc(PTPParams* params, void* private, if (written != -1) *putlen = written; else - return PTP_RC_GeneralError; + return PTP_ERROR_IO; return PTP_RC_OK; } @@ -375,13 +380,22 @@ ptp_init_fd_handler(PTPDataHandler *hand } static uint16_t -ptp_exit_fd_handler (PTPDataHandler *handler) { +ptp_exit_fd_handler (PTPDataHandler *handler) +{ PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)handler->priv; free (priv); return PTP_RC_OK; } /* Old style transaction, based on memory */ +/* A note on memory management: + * If called with the flag PTP_DP_GETDATA, this function will internally + * allocate memory as much as necessary. The caller has to free the memory + * returned in *data. If the function returns an error, it will free any + * memory it might have allocated. The recvlen may be NULL. After the + * function returns, *data will be initialized (valid memory pointer or NULL), + * i.e. it is not necessary to initialize *data or *recvlen beforehand. + */ uint16_t ptp_transaction (PTPParams* params, PTPContainer* ptp, uint16_t flags, uint64_t sendlen, @@ -392,12 +406,17 @@ ptp_transaction (PTPParams* params, PTPC switch (flags & PTP_DP_DATA_MASK) { case PTP_DP_SENDDATA: - ret = ptp_init_send_memory_handler (&handler, *data, sendlen); - if (ret != PTP_RC_OK) return ret; + if (!data) + return PTP_ERROR_BADPARAM; + CHECK_PTP_RC(ptp_init_send_memory_handler (&handler, *data, sendlen)); break; case PTP_DP_GETDATA: - ret = ptp_init_recv_memory_handler (&handler); - if (ret != PTP_RC_OK) return ret; + if (!data) + return PTP_ERROR_BADPARAM; + *data = NULL; + if (recvlen) + *recvlen = 0; + CHECK_PTP_RC(ptp_init_recv_memory_handler (&handler)); break; default:break; } @@ -409,6 +428,11 @@ ptp_transaction (PTPParams* params, PTPC case PTP_DP_GETDATA: { unsigned long len; ptp_exit_recv_memory_handler (&handler, data, &len); + if (ret != PTP_RC_OK) { + len = 0; + free(*data); + *data = NULL; + } if (recvlen) *recvlen = len; break; @@ -438,53 +462,46 @@ ptp_transaction (PTPParams* params, PTPC uint16_t ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo) { - uint16_t ret; - unsigned long len; PTPContainer ptp; - unsigned char* di=NULL; - PTPDataHandler handler; + unsigned char *data; + unsigned int size; + int ret; - ptp_init_recv_memory_handler (&handler); - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetDeviceInfo; - ptp.Nparam=0; - len=0; - ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); - ptp_exit_recv_memory_handler (&handler, &di, &len); - if (!di) ret = PTP_RC_GeneralError; - if (ret == PTP_RC_OK) ptp_unpack_DI(params, di, deviceinfo, len); - free(di); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetDeviceInfo); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ret = ptp_unpack_DI(params, data, deviceinfo, size); + free(data); + if (ret) + return PTP_RC_OK; + else + return PTP_ERROR_IO; } uint16_t ptp_canon_eos_getdeviceinfo (PTPParams* params, PTPCanonEOSDeviceInfo*di) { - uint16_t ret; PTPContainer ptp; - PTPDataHandler handler; - unsigned long len; unsigned char *data; + unsigned int size; + int ret; - ptp_init_recv_memory_handler (&handler); - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_EOS_GetDeviceInfoEx; - ptp.Nparam=0; - len=0; - data=NULL; - ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); - ptp_exit_recv_memory_handler (&handler, &data, &len); - if (ret == PTP_RC_OK) ptp_unpack_EOS_DI(params, data, di, len); + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetDeviceInfoEx); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ret = ptp_unpack_EOS_DI(params, data, di, size); free (data); - return ret; + if (ret) + return PTP_RC_OK; + else + return PTP_ERROR_IO; } #ifdef HAVE_LIBXML2 static int -traverse_tree (PTPParams *params, int depth, xmlNodePtr node) { +traverse_tree (PTPParams *params, int depth, xmlNodePtr node) +{ xmlNodePtr next; xmlChar *xchar; - int n; + int n; char *xx; @@ -508,9 +525,10 @@ traverse_tree (PTPParams *params, int de } static int -parse_9301_cmd_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) { - xmlNodePtr next; - int cnt; +parse_9301_cmd_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) +{ + xmlNodePtr next; + int cnt; cnt = 0; next = xmlFirstElementChild (node); @@ -534,7 +552,8 @@ parse_9301_cmd_tree (PTPParams *params, } static int -parse_9301_value (PTPParams *params, const char *str, uint16_t type, PTPPropertyValue *propval) { +parse_9301_value (PTPParams *params, const char *str, uint16_t type, PTPPropertyValue *propval) +{ switch (type) { case 6: { /*UINT32*/ unsigned int x; @@ -632,7 +651,8 @@ parse_9301_value (PTPParams *params, con } static int -parse_9301_propdesc (PTPParams *params, xmlNodePtr next, PTPDevicePropDesc *dpd) { +parse_9301_propdesc (PTPParams *params, xmlNodePtr next, PTPDevicePropDesc *dpd) +{ int type = -1; if (!next) @@ -720,7 +740,8 @@ parse_9301_propdesc (PTPParams *params, } static int -parse_9301_prop_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) { +parse_9301_prop_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) +{ xmlNodePtr next; int cnt; unsigned int i; @@ -751,10 +772,7 @@ parse_9301_prop_tree (PTPParams *params, if (params->deviceproperties[i].desc.DevicePropertyCode == p) break; if (i == params->nrofdeviceproperties) { - if (!i) - params->deviceproperties = malloc(sizeof(params->deviceproperties[0])); - else - params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); + params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); memset(¶ms->deviceproperties[i],0,sizeof(params->deviceproperties[0])); params->nrofdeviceproperties++; } else { @@ -771,9 +789,10 @@ parse_9301_prop_tree (PTPParams *params, } static int -parse_9301_event_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) { - xmlNodePtr next; - int cnt; +parse_9301_event_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) +{ + xmlNodePtr next; + int cnt; cnt = 0; next = xmlFirstElementChild (node); @@ -797,7 +816,8 @@ parse_9301_event_tree (PTPParams *params } static int -parse_9301_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) { +parse_9301_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) +{ xmlNodePtr next; next = xmlFirstElementChild (node); @@ -825,7 +845,8 @@ parse_9301_tree (PTPParams *params, xmlN } static uint16_t -ptp_olympus_parse_output_xml(PTPParams* params, char*data, int len, xmlNodePtr *code) { +ptp_olympus_parse_output_xml(PTPParams* params, char*data, int len, xmlNodePtr *code) +{ xmlDocPtr docin; xmlNodePtr docroot, output, next; int result, xcode; @@ -893,26 +914,19 @@ uint16_t ptp_olympus_getdeviceinfo (PTPParams* params, PTPDeviceInfo *di) { #ifdef HAVE_LIBXML2 - uint16_t ret; PTPContainer ptp; - PTPDataHandler handler; + uint16_t ret; unsigned char *data; - unsigned long len; + unsigned int size; xmlNodePtr code; memset (di, 0, sizeof(PTPDeviceInfo)); - ptp_init_recv_memory_handler (&handler); - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_OLYMPUS_GetDeviceInfo; - ptp.Nparam = 0; - len = 0; - data = NULL; - ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); - ptp_exit_recv_memory_handler (&handler, &data, &len); - - ret = ptp_olympus_parse_output_xml(params,(char*)data,len,&code); + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetDeviceInfo); + ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); + /* TODO: check for error, only parse_output_xml if ret == PTP_RC_OK? + * where is 'data' going to be deallocated? */ + ret = ptp_olympus_parse_output_xml(params,(char*)data,size,&code); if (ret != PTP_RC_OK) return ret; @@ -926,39 +940,21 @@ ptp_olympus_getdeviceinfo (PTPParams* pa } uint16_t -ptp_olympus_opensession (PTPParams* params, unsigned char**data, unsigned long *len) +ptp_olympus_opensession (PTPParams* params, unsigned char**data, unsigned int *len) { - uint16_t ret; PTPContainer ptp; - PTPDataHandler handler; - ptp_init_recv_memory_handler (&handler); - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_OLYMPUS_OpenSession; - ptp.Nparam = 0; - *len = 0; - *data = NULL; - ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); - ptp_exit_recv_memory_handler (&handler, data, len); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OpenSession); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, len); } uint16_t -ptp_olympus_getcameraid (PTPParams* params, unsigned char**data, unsigned long *len) +ptp_olympus_getcameraid (PTPParams* params, unsigned char**data, unsigned int *len) { - uint16_t ret; PTPContainer ptp; - PTPDataHandler handler; - ptp_init_recv_memory_handler (&handler); - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_OLYMPUS_GetCameraID; - ptp.Nparam = 0; - *len = 0; - *data = NULL; - ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); - ptp_exit_recv_memory_handler (&handler, data, len); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetCameraID); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, len); } /** @@ -975,14 +971,14 @@ ptp_olympus_getcameraid (PTPParams* para uint16_t ptp_generic_no_data (PTPParams* params, uint16_t code, unsigned int n_param, ...) { - PTPContainer ptp; - va_list args; - unsigned int i; + PTPContainer ptp; + va_list args; + unsigned int i; if( n_param > 5 ) - return PTP_RC_InvalidParameter; + return PTP_ERROR_BADPARAM; - PTP_CNT_INIT(ptp); + memset(&ptp, 0, sizeof(ptp)); ptp.Code=code; ptp.Nparam=n_param; @@ -1006,8 +1002,8 @@ ptp_generic_no_data (PTPParams* params, uint16_t ptp_opensession (PTPParams* params, uint32_t session) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; + uint16_t ret; ptp_debug(params,"PTP: Opening session"); @@ -1022,18 +1018,17 @@ ptp_opensession (PTPParams* params, uint /* no split headers */ params->split_header_data = 0; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_OpenSession; - ptp.Param1=session; - ptp.Nparam=1; + PTP_CNT_INIT(ptp, PTP_OC_OpenSession, session); ret=ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL); + /* TODO: check for error */ /* now set the global session id to current session number */ params->session_id=session; return ret; } void -ptp_free_devicepropvalue(uint16_t dt, PTPPropertyValue* dpd) { +ptp_free_devicepropvalue(uint16_t dt, PTPPropertyValue* dpd) +{ switch (dt) { case PTP_DTC_INT8: case PTP_DTC_UINT8: case PTP_DTC_UINT16: case PTP_DTC_INT16: @@ -1047,12 +1042,10 @@ ptp_free_devicepropvalue(uint16_t dt, PT case PTP_DTC_AUINT32: case PTP_DTC_AINT32: case PTP_DTC_AUINT64: case PTP_DTC_AINT64: case PTP_DTC_AUINT128: case PTP_DTC_AINT128: - if (dpd->a.v) - free(dpd->a.v); + free(dpd->a.v); break; case PTP_DTC_STR: - if (dpd->str) - free(dpd->str); + free(dpd->str); break; } } @@ -1126,14 +1119,16 @@ ptp_free_objectpropdesc(PTPObjectPropDes * Return values: Some PTP_RC_* code. **/ void -ptp_free_params (PTPParams *params) { +ptp_free_params (PTPParams *params) +{ unsigned int i; - if (params->cameraname) free (params->cameraname); - if (params->wifi_profiles) free (params->wifi_profiles); + free (params->cameraname); + free (params->wifi_profiles); for (i=0;i<params->nrofobjects;i++) ptp_free_object (¶ms->objects[i]); free (params->objects); + free (params->storageids.Storage); free (params->events); for (i=0;i<params->nrofcanon_props;i++) { free (params->canon_props[i].data); @@ -1160,19 +1155,15 @@ ptp_free_params (PTPParams *params) { uint16_t ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids) { - uint16_t ret; - PTPContainer ptp; - unsigned int len; - unsigned char* sids=NULL; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetStorageIDs; - ptp.Nparam=0; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len); - if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len); - free(sids); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetStorageIDs); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_SIDs(params, data, storageids, size); + free(data); + return PTP_RC_OK; } /** @@ -1189,20 +1180,21 @@ uint16_t ptp_getstorageinfo (PTPParams* params, uint32_t storageid, PTPStorageInfo* storageinfo) { - uint16_t ret; - PTPContainer ptp; - unsigned char* si=NULL; - unsigned int len; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetStorageInfo; - ptp.Param1=storageid; - ptp.Nparam=1; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &si, &len); - if (ret == PTP_RC_OK) ptp_unpack_SI(params, si, storageinfo, len); - free(si); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetStorageInfo, storageid); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data || !size) + return PTP_RC_GeneralError; + memset(storageinfo, 0, sizeof(*storageinfo)); + if (!ptp_unpack_SI(params, data, storageinfo, size)) { + free(data); + return PTP_RC_GeneralError; + } + free(data); + return PTP_RC_OK; } /** @@ -1224,21 +1216,18 @@ ptp_getobjecthandles (PTPParams* params, uint32_t objectformatcode, uint32_t associationOH, PTPObjectHandles* objecthandles) { - uint16_t ret; - PTPContainer ptp; - unsigned char* oh=NULL; - unsigned int len; + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetObjectHandles; - ptp.Param1=storage; - ptp.Param2=objectformatcode; - ptp.Param3=associationOH; - ptp.Nparam=3; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oh, &len); + objecthandles->Handler = NULL; + objecthandles->n = 0; + + PTP_CNT_INIT(ptp, PTP_OC_GetObjectHandles, storage, objectformatcode, associationOH); + ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); if (ret == PTP_RC_OK) { - ptp_unpack_OH(params, oh, objecthandles, len); + ptp_unpack_OH(params, data, objecthandles, size); } else { if ( (storage == 0xffffffff) && (objectformatcode == 0) && @@ -1252,7 +1241,7 @@ ptp_getobjecthandles (PTPParams* params, ret = PTP_RC_OK; } } - free(oh); + free(data); return ret; } @@ -1261,19 +1250,10 @@ ptp_getfilesystemmanifest (PTPParams* pa uint32_t objectformatcode, uint32_t associationOH, unsigned char** data) { - uint16_t ret; PTPContainer ptp; - unsigned int len; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetFilesystemManifest; - ptp.Param1=storage; - ptp.Param2=objectformatcode; - ptp.Param3=associationOH; - ptp.Nparam=3; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &len); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetFilesystemManifest, storage, objectformatcode, associationOH); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL); } /** @@ -1295,23 +1275,15 @@ ptp_getnumobjects (PTPParams* params, ui uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetNumObjects; - ptp.Param1=storage; - ptp.Param2=objectformatcode; - ptp.Param3=associationOH; - ptp.Nparam=3; - ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if (ret == PTP_RC_OK) { - if (ptp.Nparam >= 1) - *numobs = ptp.Param1; - else - ret = PTP_RC_GeneralError; - } - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetNumObjects, storage, objectformatcode, associationOH); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + if (ptp.Nparam >= 1) + *numobs = ptp.Param1; + else + return PTP_RC_GeneralError; + return PTP_RC_OK; } /** @@ -1325,16 +1297,13 @@ ptp_getnumobjects (PTPParams* params, ui uint16_t ptp_canon_eos_bulbstart (PTPParams* params) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_BulbStart; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000)) - ret = ptp.Param1; - return ret; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_BulbStart); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000)) + return ptp.Param1; + return PTP_RC_OK; } /** @@ -1351,17 +1320,14 @@ ptp_canon_eos_bulbstart (PTPParams* para uint16_t ptp_canon_eos_capture (PTPParams* params, uint32_t *result) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_RemoteRelease; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_RemoteRelease); *result = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1)) + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + if (ptp.Nparam >= 1) *result = ptp.Param1; - return ret; + return PTP_RC_OK; } /** @@ -1375,16 +1341,13 @@ ptp_canon_eos_capture (PTPParams* params uint16_t ptp_canon_eos_bulbend (PTPParams* params) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_BulbEnd; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000)) - ret = ptp.Param1; - return ret; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_BulbEnd); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000)) + return ptp.Param1; + return PTP_RC_OK; } /** @@ -1401,20 +1364,15 @@ uint16_t ptp_getobjectinfo (PTPParams* params, uint32_t handle, PTPObjectInfo* objectinfo) { - uint16_t ret; - PTPContainer ptp; - unsigned char* oi=NULL; - unsigned int len; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetObjectInfo; - ptp.Param1=handle; - ptp.Nparam=1; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oi, &len); - if (ret == PTP_RC_OK) ptp_unpack_OI(params, oi, objectinfo, len); - free(oi); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_GetObjectInfo, handle); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_OI(params, data, objectinfo, size); + free(data); + return PTP_RC_OK; } /** @@ -1432,14 +1390,30 @@ uint16_t ptp_getobject (PTPParams* params, uint32_t handle, unsigned char** object) { PTPContainer ptp; - unsigned int len; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetObject; - ptp.Param1=handle; - ptp.Nparam=1; - len=0; - return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, &len); + PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, NULL); +} + +/** + * ptp_getobject_with_size: + * params: PTPParams* + * handle - Object handle + * object - pointer to data area + * size - pointer to uint, returns size of object + * + * Get object 'handle' from device and store the data in newly + * allocated 'object'. + * + * Return values: Some PTP_RC_* code. + **/ +uint16_t +ptp_getobject_with_size (PTPParams* params, uint32_t handle, unsigned char** object, unsigned int *size) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, size); } /** @@ -1458,10 +1432,7 @@ ptp_getobject_to_handler (PTPParams* par { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetObject; - ptp.Param1=handle; - ptp.Nparam=1; + PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle); return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler); } @@ -1483,11 +1454,8 @@ ptp_getobject_tofd (PTPParams* params, u PTPDataHandler handler; uint16_t ret; + PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle); ptp_init_fd_handler (&handler, fd); - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetObject; - ptp.Param1=handle; - ptp.Nparam=1; ret = ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler); ptp_exit_fd_handler (&handler); return ret; @@ -1514,17 +1482,34 @@ ptp_getpartialobject (PTPParams* params, { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetPartialObject; - ptp.Param1=handle; - ptp.Param2=offset; - ptp.Param3=maxbytes; - ptp.Nparam=3; - *len=0; + PTP_CNT_INIT(ptp, PTP_OC_GetPartialObject, handle, offset, maxbytes); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len); } /** + * ptp_getpartialobject_to_handler: + * params: PTPParams* + * handle - Object handle + * offset - Offset into object + * maxbytes - Maximum of bytes to read + * handler - a ptp data handler + * + * Get object 'handle' from device and send the data to the + * data handler. Start from offset and read at most maxbytes. + * + * Return values: Some PTP_RC_* code. + **/ +uint16_t +ptp_getpartialobject_to_handler (PTPParams* params, uint32_t handle, uint32_t offset, + uint32_t maxbytes, PTPDataHandler *handler) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_GetPartialObject, handle, offset, maxbytes); + return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler); +} + +/** * ptp_getthumb: * params: PTPParams* * handle - Object handle @@ -1540,11 +1525,7 @@ ptp_getthumb (PTPParams* params, uint32_ { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetThumb; - ptp.Param1=handle; - ptp.Nparam=1; - *len = 0; + PTP_CNT_INIT(ptp, PTP_OC_GetThumb, handle); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len); } @@ -1562,17 +1543,9 @@ uint16_t ptp_deleteobject (PTPParams* params, uint32_t handle, uint32_t ofc) { PTPContainer ptp; - uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_DeleteObject; - ptp.Param1=handle; - ptp.Param2=ofc; - ptp.Nparam=2; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if (ret != PTP_RC_OK) { - return ret; - } + PTP_CNT_INIT(ptp, PTP_OC_DeleteObject, handle, ofc); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); /* If the object is cached and could be removed, cleanse cache. */ ptp_remove_object_from_cache(params, handle); return PTP_RC_OK; @@ -1601,20 +1574,15 @@ ptp_sendobjectinfo (PTPParams* params, u uint32_t* parenthandle, uint32_t* handle, PTPObjectInfo* objectinfo) { - uint16_t ret; - PTPContainer ptp; - unsigned char* oidata=NULL; - uint32_t size; + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_SendObjectInfo; - ptp.Param1=*store; - ptp.Param2=*parenthandle; - ptp.Nparam=2; - - size=ptp_pack_OI(params, objectinfo, &oidata); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL); - free(oidata); + PTP_CNT_INIT(ptp, PTP_OC_SendObjectInfo, *store, *parenthandle); + size = ptp_pack_OI(params, objectinfo, &data); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); *store=ptp.Param1; *parenthandle=ptp.Param2; *handle=ptp.Param3; @@ -1637,10 +1605,7 @@ ptp_sendobject (PTPParams* params, unsig { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_SendObject; - ptp.Nparam=0; - + PTP_CNT_INIT(ptp, PTP_OC_SendObject); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL); } @@ -1658,11 +1623,9 @@ ptp_sendobject (PTPParams* params, unsig uint16_t ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler *handler, uint64_t size) { - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_SendObject; - ptp.Nparam=0; + PTP_CNT_INIT(ptp, PTP_OC_SendObject); return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler); } @@ -1685,10 +1648,8 @@ ptp_sendobject_fromfd (PTPParams* params PTPDataHandler handler; uint16_t ret; + PTP_CNT_INIT(ptp, PTP_OC_SendObject); ptp_init_fd_handler (&handler, fd); - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_SendObject; - ptp.Nparam=0; ret = ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, &handler); ptp_exit_fd_handler (&handler); return ret; @@ -1700,49 +1661,47 @@ uint16_t ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc* devicepropertydesc) { - PTPContainer ptp; - uint16_t ret; - unsigned int len; - unsigned char* dpd=NULL; + PTPContainer ptp; + uint16_t ret = PTP_RC_OK; + unsigned char *data; + unsigned int size; + PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropDesc, propcode); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_GetDevicePropDesc; - ptp.Param1 = propcode; - ptp.Nparam = 1; - len = 0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpd, &len); + if (!data) { + ptp_debug (params, "no data received for getdevicepropdesc"); + return PTP_RC_InvalidDevicePropFormat; + } - if (ret == PTP_RC_OK) { - if (params->device_flags & DEVICE_FLAG_OLYMPUS_XML_WRAPPED) { + if (params->device_flags & DEVICE_FLAG_OLYMPUS_XML_WRAPPED) { #ifdef HAVE_LIBXML2 - xmlNodePtr code; + xmlNodePtr code; - ret = ptp_olympus_parse_output_xml (params,(char*)dpd,len,&code); - if (ret == PTP_RC_OK) { - int x; + ret = ptp_olympus_parse_output_xml (params,(char*)data,size,&code); + if (ret == PTP_RC_OK) { + int x; - if ( (xmlChildElementCount(code) == 1) && + if ( (xmlChildElementCount(code) == 1) && (!strcmp((char*)code->name,"c1014")) - ) { - code = xmlFirstElementChild (code); + ) { + code = xmlFirstElementChild (code); - if ( (sscanf((char*)code->name,"p%x", &x)) && + if ( (sscanf((char*)code->name,"p%x", &x)) && (x == propcode) - ) { - ret = parse_9301_propdesc (params, xmlFirstElementChild (code), devicepropertydesc); - xmlFreeDoc(code->doc); - } + ) { + ret = parse_9301_propdesc (params, xmlFirstElementChild (code), devicepropertydesc); + xmlFreeDoc(code->doc); } - } else { - ptp_debug(params,"failed to parse output xml, ret %x?", ret); } -#endif } else { - ptp_unpack_DPD(params, dpd, devicepropertydesc, len); + ptp_debug(params,"failed to parse output xml, ret %x?", ret); } +#endif + } else { + ptp_unpack_DPD(params, data, devicepropertydesc, size); } - free(dpd); + free(data); return ret; } @@ -1751,26 +1710,17 @@ uint16_t ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode, PTPPropertyValue* value, uint16_t datatype) { - PTPContainer ptp; - uint16_t ret; - unsigned int len, offset; - unsigned char* dpv=NULL; - + PTPContainer ptp; + unsigned char *data; + unsigned int size, offset = 0; + uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_GetDevicePropValue; - ptp.Param1=propcode; - ptp.Nparam=1; - len=offset=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &len); - if (ret == PTP_RC_OK) { - int ret2 = ptp_unpack_DPV(params, dpv, &offset, len, value, datatype); - if (!ret2) { - ptp_debug (params, "ptp_getdevicepropvalue: unpacking DPV failed"); - ret = PTP_RC_GeneralError; - } - } - free(dpv); + PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropValue, propcode); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ret = ptp_unpack_DPV(params, data, &offset, size, value, datatype) ? PTP_RC_OK : PTP_RC_GeneralError; + if (ret != PTP_RC_OK) + ptp_debug (params, "ptp_getdevicepropvalue: unpacking DPV failed"); + free(data); return ret; } @@ -1778,18 +1728,15 @@ uint16_t ptp_setdevicepropvalue (PTPParams* params, uint16_t propcode, PTPPropertyValue *value, uint16_t datatype) { - PTPContainer ptp; - uint16_t ret; - uint32_t size; - unsigned char* dpv=NULL; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_SetDevicePropValue; - ptp.Param1=propcode; - ptp.Nparam=1; - size=ptp_pack_DPV(params, value, &dpv, datatype); - ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL); - free(dpv); + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_SetDevicePropValue, propcode); + size=ptp_pack_DPV(params, value, &data, datatype); + ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); return ret; } @@ -1816,20 +1763,15 @@ ptp_ek_sendfileobjectinfo (PTPParams* pa uint32_t* parenthandle, uint32_t* handle, PTPObjectInfo* objectinfo) { - uint16_t ret; - PTPContainer ptp; - unsigned char* oidata=NULL; - uint32_t size; + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_EK_SendFileObjectInfo; - ptp.Param1=*store; - ptp.Param2=*parenthandle; - ptp.Nparam=2; - - size=ptp_pack_OI(params, objectinfo, &oidata); - ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL); - free(oidata); + PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObjectInfo, *store, *parenthandle); + size=ptp_pack_OI(params, objectinfo, &data); + ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); *store=ptp.Param1; *parenthandle=ptp.Param2; *handle=ptp.Param3; @@ -1852,9 +1794,7 @@ ptp_ek_getserial (PTPParams* params, uns { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_EK_GetSerial; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, PTP_OC_EK_GetSerial); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -1874,9 +1814,7 @@ ptp_ek_setserial (PTPParams* params, uns { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_EK_SetSerial; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, PTP_OC_EK_SetSerial); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); } @@ -1886,9 +1824,7 @@ ptp_ek_9007 (PTPParams* params, unsigned { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = 0x9007; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, 0x9007); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -1897,15 +1833,13 @@ uint16_t ptp_ek_9009 (PTPParams* params, uint32_t *p1, uint32_t *p2) { PTPContainer ptp; - uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code = 0x9009; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); + PTP_CNT_INIT(ptp, 0x9009); + *p1 = *p2 = 0; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *p1 = ptp.Param1; *p2 = ptp.Param2; - return ret; + return PTP_RC_OK; } /* unclear yet, but I guess it returns the info from 9008 */ @@ -1914,9 +1848,7 @@ ptp_ek_900c (PTPParams* params, unsigned { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = 0x900c; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, 0x900c); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); /* returned data is 16bit,16bit,32bit,32bit */ } @@ -1934,17 +1866,15 @@ ptp_ek_900c (PTPParams* params, unsigned uint16_t ptp_ek_settext (PTPParams* params, PTPEKTextParams *text) { - PTPContainer ptp; - uint16_t ret; - unsigned int size; - unsigned char *data; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_EK_SetText; - ptp.Nparam = 0; + PTPContainer ptp; + uint16_t ret; + unsigned char *data = 0; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_EK_SetText); if (0 == (size = ptp_pack_EK_text(params, text, &data))) return PTP_ERROR_BADPARAM; - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); free(data); return ret; } @@ -1965,10 +1895,7 @@ ptp_ek_sendfileobject (PTPParams* params { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_EK_SendFileObject; - ptp.Nparam=0; - + PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObject); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL); } @@ -1988,9 +1915,7 @@ ptp_ek_sendfileobject_from_handler (PTPP { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_EK_SendFileObject; - ptp.Nparam=0; + PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObject); return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler); } @@ -2024,18 +1949,14 @@ uint16_t ptp_canon_getpartialobjectinfo (PTPParams* params, uint32_t handle, uint32_t p2, uint32_t* size, uint32_t* rp2) { - uint16_t ret; - PTPContainer ptp; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetPartialObjectInfo; - ptp.Param1=handle; - ptp.Param2=p2; - ptp.Nparam=2; - ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPartialObjectInfo, handle, p2); + *size = *rp2 = 0; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *size=ptp.Param1; *rp2=ptp.Param2; - return ret; + return PTP_RC_OK; } /** @@ -2052,13 +1973,9 @@ uint16_t ptp_canon_get_mac_address (PTPParams* params, unsigned char **mac) { PTPContainer ptp; - unsigned int size = 0; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetMACAddress; - ptp.Nparam=0; - *mac = NULL; - return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, mac, &size); + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetMACAddress); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, mac, NULL); } /** @@ -2080,18 +1997,13 @@ ptp_canon_get_directory (PTPParams* para uint32_t **flags /* size(handles->n) */ ) { PTPContainer ptp; - unsigned char *dir = NULL; - unsigned int size = 0; + unsigned char *data; uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetDirectory; - ptp.Nparam=0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dir, &size); - if (ret != PTP_RC_OK) - return ret; - ret = ptp_unpack_canon_directory(params, dir, ptp.Param1, handles, oinfos, flags); - free (dir); + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetDirectory); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL)); + ret = ptp_unpack_canon_directory(params, data, ptp.Param1, handles, oinfos, flags); + free (data); return ret; } @@ -2110,17 +2022,13 @@ ptp_canon_get_directory (PTPParams* para uint16_t ptp_canon_gettreeinfo (PTPParams* params, uint32_t *out) { - PTPContainer ptp; - uint16_t ret; + PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_GetTreeInfo; - ptp.Nparam = 1; - ptp.Param1 = 0xf; - ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ((ret == PTP_RC_OK) && (ptp.Nparam>0)) + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetTreeInfo, 0xf); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + if (ptp.Nparam > 0) *out = ptp.Param1; - return ret; + return PTP_RC_OK; } /** @@ -2137,18 +2045,9 @@ uint16_t ptp_canon_getpairinginfo (PTPParams* params, uint32_t nr, unsigned char **data, unsigned int *size) { PTPContainer ptp; - uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_GetPairingInfo; - ptp.Nparam = 1; - ptp.Param1 = nr; - *data = NULL; - *size = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); - if (ret != PTP_RC_OK) - return ret; - return PTP_RC_OK; + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPairingInfo, nr); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } /** @@ -2167,32 +2066,29 @@ uint16_t ptp_canon_gettreesize (PTPParams* params, PTPCanon_directtransfer_entry **entries, unsigned int *cnt) { - PTPContainer ptp; - uint16_t ret; - unsigned char *out = NULL, *cur; - unsigned int i, size; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_GetTreeSize; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &out, &size); - if (ret != PTP_RC_OK) - return ret; - *cnt = dtoh32a(out); + PTPContainer ptp; + uint16_t ret = PTP_RC_OK; + unsigned char *data, *cur; + unsigned int size, i; + + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetTreeSize); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + *cnt = dtoh32a(data); *entries = malloc(sizeof(PTPCanon_directtransfer_entry)*(*cnt)); if (!*entries) { - free (out); - return PTP_RC_GeneralError; + ret = PTP_RC_GeneralError; + goto exit; } - cur = out+4; + cur = data+4; for (i=0;i<*cnt;i++) { unsigned char len; (*entries)[i].oid = dtoh32a(cur); - (*entries)[i].str = ptp_unpack_string(params, cur, 4, &len); + (*entries)[i].str = ptp_unpack_string(params, cur, 4, size-(cur-data-4), &len); cur += 4+(cur[4]*2+1); } - free (out); - return PTP_RC_OK; +exit: + free (data); + return ret; } /** @@ -2217,63 +2113,124 @@ ptp_canon_gettreesize (PTPParams* params uint16_t ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent) { - uint16_t ret; - PTPContainer ptp; - unsigned char *evdata = NULL; - unsigned int len; + PTPContainer ptp; + unsigned char *data; + unsigned int size; + PTP_CNT_INIT(ptp, PTP_OC_CANON_CheckEvent); *isevent=0; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_CheckEvent; - ptp.Nparam=0; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &evdata, &len); - if (evdata!=NULL) { - if (ret == PTP_RC_OK) { - ptp_unpack_EC(params, evdata, event, len); - *isevent=1; - } - free(evdata); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (data && size) { /* check if we had a successfull call with data */ + ptp_unpack_EC(params, data, event, size); + *isevent=1; + free(data); } - return ret; + return PTP_RC_OK; } uint16_t -ptp_add_event (PTPParams *params, PTPContainer *evt) { - if (params->nrofevents) - params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1)); - else - params->events = malloc(sizeof(PTPContainer)*1); +ptp_add_event (PTPParams *params, PTPContainer *evt) +{ + params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1)); memcpy (¶ms->events[params->nrofevents],evt,1*sizeof(PTPContainer)); params->nrofevents += 1; return PTP_RC_OK; } +static void +handle_event_internal (PTPParams *params, PTPContainer *event) +{ + /* handle some PTP stack internal events */ + switch (event->Code) { + case PTP_EC_DevicePropChanged: { + unsigned int i; + + /* mark the property for a forced refresh on the next query */ + for (i=0;i<params->nrofdeviceproperties;i++) + if (params->deviceproperties[i].desc.DevicePropertyCode == event->Param1) { + params->deviceproperties[i].timestamp = 0; + break; + } + break; + } + case PTP_EC_StoreAdded: + case PTP_EC_StoreRemoved: { + int i; + + /* refetch storage IDs and also invalidate whole object tree */ + free (params->storageids.Storage); + params->storageids.Storage = NULL; + params->storageids.n = 0; + ptp_getstorageids (params, ¶ms->storageids); + + /* free object storage as it might be associated with the storage ids */ + /* FIXME: enhance and just delete the ones from the storage */ + for (i=0;i<params->nrofobjects;i++) + ptp_free_object (¶ms->objects[i]); + free (params->objects); + params->objects = NULL; + params->nrofobjects = 0; + + params->storagechanged = 1; + break; + } + default: /* check if we should handle it internally too */ + break; + } +} + uint16_t -ptp_check_event (PTPParams *params) { - PTPContainer event; - uint16_t ret; +ptp_check_event_queue (PTPParams *params) +{ + PTPContainer event; + uint16_t ret; + + /* We try to do a event check without I/O */ + /* Basically this means just looking at the meanwhile queued events */ + + ret = params->event_check_queue(params,&event); + + if (ret == PTP_RC_OK) { + ptp_debug (params, "event: nparams=0x%X, code=0x%X, trans_id=0x%X, p1=0x%X, p2=0x%X, p3=0x%X", event.Nparam,event.Code,event.Transaction_ID, event.Param1, event.Param2, event.Param3); + ptp_add_event (params, &event); + handle_event_internal (params, &event); + } + if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */ + ret = PTP_RC_OK; + return ret; +} +uint16_t +ptp_check_event (PTPParams *params) +{ + PTPContainer event; + uint16_t ret; + + /* Method offered by Nikon DSLR, Nikon 1, and some older Nikon Coolpix P* + * The Nikon Coolpix P2 however does not return anything. So if we never get + * events from here, use the ptp "interrupt" method */ if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) && ptp_operation_issupported(params, PTP_OC_NIKON_CheckEvent) ) { - unsigned int evtcnt; - PTPContainer *xevent = NULL; + unsigned int evtcnt = 0, i; + PTPContainer *xevent = NULL; ret = ptp_nikon_check_event(params, &xevent, &evtcnt); - if (ret != PTP_RC_OK) - return ret; + if (ret != PTP_RC_OperationNotSupported) + CHECK_PTP_RC(ret); if (evtcnt) { - if (params->nrofevents) - params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents)); - else - params->events = malloc(sizeof(PTPContainer)*evtcnt); + for (i = 0; i < evtcnt; i++) + handle_event_internal (params, &xevent[i]); + params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents)); memcpy (¶ms->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer)); params->nrofevents += evtcnt; free (xevent); + params->event90c7works = 1; } - return PTP_RC_OK; + if (params->event90c7works) + return PTP_RC_OK; + /* fall through to generic event handling */ } /* should not get here ... EOS has no normal PTP events and another queue handling. */ if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) && @@ -2287,14 +2244,15 @@ ptp_check_event (PTPParams *params) { ) { int isevent; - ret = ptp_canon_checkevent (params,&event,&isevent); - if (ret!=PTP_RC_OK) - return ret; - if (isevent) + CHECK_PTP_RC(ptp_canon_checkevent (params,&event,&isevent)); + + if (isevent) { + ret = PTP_RC_OK; goto store_event; + } /* Event Emulate Mode 0 (unset) and 1-5 get interrupt events. 6-7 does not. */ if (params->canon_event_mode > 5) - return ret; + return PTP_RC_OK; /* FIXME: fallthrough or return? */ #ifdef __APPLE__ @@ -2302,7 +2260,7 @@ ptp_check_event (PTPParams *params) { * for interrupts, they have no timeout for it. 2010/08/23 * Check back in 2011 or so. -Marcus */ - return ret; + return PTP_RC_OK; #endif } ret = params->event_check(params,&event); @@ -2311,14 +2269,38 @@ store_event: if (ret == PTP_RC_OK) { ptp_debug (params, "event: nparams=0x%X, code=0x%X, trans_id=0x%X, p1=0x%X, p2=0x%X, p3=0x%X", event.Nparam,event.Code,event.Transaction_ID, event.Param1, event.Param2, event.Param3); ptp_add_event (params, &event); + + handle_event_internal (params, &event); + + + } + if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */ + ret = PTP_RC_OK; + return ret; +} + +uint16_t +ptp_wait_event (PTPParams *params) +{ + PTPContainer event; + uint16_t ret; + + ret = params->event_wait(params,&event); + if (ret == PTP_RC_OK) { + ptp_debug (params, "event: nparams=0x%X, code=0x%X, trans_id=0x%X, p1=0x%X, p2=0x%X, p3=0x%X", event.Nparam,event.Code,event.Transaction_ID, event.Param1, event.Param2, event.Param3); + ptp_add_event (params, &event); + + handle_event_internal (params, &event); } if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */ ret = PTP_RC_OK; return ret; } + int -ptp_get_one_event(PTPParams *params, PTPContainer *event) { +ptp_get_one_event(PTPParams *params, PTPContainer *event) +{ if (!params->nrofevents) return 0; memcpy (event, params->events, sizeof(PTPContainer)); @@ -2347,33 +2329,27 @@ ptp_get_one_event(PTPParams *params, PTP uint16_t ptp_canon_eos_getevent (PTPParams* params, PTPCanon_changes_entry **entries, int *nrofentries) { - PTPContainer ptp; - uint16_t ret; - unsigned int size = 0; - unsigned char *data = NULL; + PTPContainer ptp; + unsigned char *data; + unsigned int size; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetEvent); *nrofentries = 0; *entries = NULL; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_GetEvent; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret != PTP_RC_OK) return ret; - *nrofentries = ptp_unpack_CANON_changes(params,data,size,entries); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + *nrofentries = ptp_unpack_CANON_changes(params,data,size,entries); free (data); return PTP_RC_OK; } uint16_t -ptp_check_eos_events (PTPParams *params) { - uint16_t ret; +ptp_check_eos_events (PTPParams *params) +{ PTPCanon_changes_entry *entries = NULL, *nentries; int nrofentries = 0; while (1) { /* call it repeatedly until the camera does not report any */ - ret = ptp_canon_eos_getevent (params, &entries, &nrofentries); - if (ret != PTP_RC_OK) - return ret; + CHECK_PTP_RC(ptp_canon_eos_getevent (params, &entries, &nrofentries)); if (!nrofentries) return PTP_RC_OK; @@ -2394,7 +2370,8 @@ ptp_check_eos_events (PTPParams *params) } int -ptp_get_one_eos_event (PTPParams *params, PTPCanon_changes_entry *entry) { +ptp_get_one_eos_event (PTPParams *params, PTPCanon_changes_entry *entry) +{ if (!params->nrofbacklogentries) return 0; memcpy (entry, params->backlogentries, sizeof(*entry)); @@ -2443,34 +2420,24 @@ uint16_t ptp_canon_eos_getstorageids (PTPParams* params, PTPStorageIDs* storageids) { PTPContainer ptp; - unsigned int len = 0; - uint16_t ret; - unsigned char* sids=NULL; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_GetStorageIDs; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len); - if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len); - free(sids); - return ret; + unsigned char *data; + unsigned int size; + + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetStorageIDs); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_SIDs(params, data, storageids, size); + free(data); + return PTP_RC_OK; } uint16_t ptp_canon_eos_getstorageinfo (PTPParams* params, uint32_t p1, unsigned char **data, unsigned int *size) { - PTPContainer ptp; - uint16_t ret; + PTPContainer ptp; - *size = 0; - *data = NULL; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_GetStorageInfo; - ptp.Nparam = 1; - ptp.Param1 = p1; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetStorageInfo, p1); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); /* FIXME: do stuff with data */ - return ret; } uint16_t @@ -2479,40 +2446,50 @@ ptp_canon_eos_getobjectinfoex ( PTPCANONFolderEntry **entries, unsigned int *nrofentries ) { PTPContainer ptp; - unsigned int i, size = 0; + uint16_t ret = PTP_RC_OK; unsigned char *data, *xdata; - uint16_t ret; - - data = NULL; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_GetObjectInfoEx; - ptp.Nparam = 3; - ptp.Param1 = storageid; - ptp.Param2 = oid; - ptp.Param3 = unk; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret != PTP_RC_OK) - return ret; + unsigned int size, i; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetObjectInfoEx, storageid, oid, unk); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); if (!data) { *nrofentries = 0; return PTP_RC_OK; } + if (size < 4) { + ret = PTP_RC_GeneralError; + goto exit; + } + /* check for integer overflow */ + if (dtoh32a(data) >= INT_MAX/sizeof(PTPCANONFolderEntry)) { + ret = PTP_RC_GeneralError; + goto exit; + } + *nrofentries = dtoh32a(data); *entries = malloc(*nrofentries * sizeof(PTPCANONFolderEntry)); if (!*entries) { - free (data); - return PTP_RC_GeneralError; + ret = PTP_RC_GeneralError; + goto exit; } xdata = data+sizeof(uint32_t); for (i=0;i<*nrofentries;i++) { + if ((dtoh32a(xdata) + (xdata-data)) > size) { + ptp_debug (params, "reading canon FEs run over read data size?\n"); + free (*entries); + *entries = NULL; + *nrofentries = 0; + ret = PTP_RC_GeneralError; + goto exit; + } ptp_unpack_Canon_EOS_FE (params, &xdata[4], &((*entries)[i])); xdata += dtoh32a(xdata); } +exit: free (data); - return PTP_RC_OK; + return ret; } /** @@ -2535,16 +2512,9 @@ uint16_t ptp_canon_eos_getpartialobject (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data) { PTPContainer ptp; - unsigned int size = 0; - *data = NULL; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_GetPartialObject; - ptp.Nparam = 3; - ptp.Param1 = oid; - ptp.Param2 = offset; - ptp.Param3 = xsize; - return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &size); + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetPartialObject, oid, offset, xsize); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL); } uint16_t @@ -2552,9 +2522,7 @@ ptp_canon_eos_setdevicepropvalueex (PTPP { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_SetDevicePropValueEx; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_SetDevicePropValueEx); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); } @@ -2564,12 +2532,11 @@ ptp_canon_eos_setdevicepropvalue (PTPPar ) { PTPContainer ptp; uint16_t ret; + unsigned char *data = NULL; unsigned int i, size; - unsigned char *data; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_EOS_SetDevicePropValueEx; - ptp.Nparam = 0; + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_SetDevicePropValueEx); + for (i=0;i<params->nrofcanon_props;i++) if (params->canon_props[i].proptype == propcode) break; @@ -2599,12 +2566,12 @@ ptp_canon_eos_setdevicepropvalue (PTPPar break; default: if (datatype != PTP_DTC_STR) { - data = calloc(sizeof(uint32_t),3); + data = calloc(3,sizeof(uint32_t)); if (!data) return PTP_RC_GeneralError; size = sizeof(uint32_t)*3; } else { size = strlen(value->str) + 1 + 8; - data = calloc(sizeof(char),size); + data = calloc(size,sizeof(char)); if (!data) return PTP_RC_GeneralError; } switch (datatype) { @@ -2666,24 +2633,17 @@ ptp_canon_getpartialobject (PTPParams* p uint32_t pos, unsigned char** block, uint32_t* readnum) { - uint16_t ret; - PTPContainer ptp; - unsigned char *data=NULL; - unsigned int len; + PTPContainer ptp; + uint16_t ret; + unsigned char *data; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetPartialObjectEx; - ptp.Param1=handle; - ptp.Param2=offset; - ptp.Param3=size; - ptp.Param4=pos; - ptp.Nparam=4; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len); + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPartialObjectEx, handle, offset, size, pos); + ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL); if (ret==PTP_RC_OK) { *block=data; *readnum=ptp.Param1; } + free (data); return ret; } @@ -2706,15 +2666,13 @@ ptp_canon_getpartialobject (PTPParams* p uint16_t ptp_canon_getviewfinderimage (PTPParams* params, unsigned char** image, uint32_t* size) { - uint16_t ret; - PTPContainer ptp; - unsigned int len; + PTPContainer ptp; + uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetViewfinderImage; - ptp.Nparam=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image, &len); - if (ret==PTP_RC_OK) *size=ptp.Param1; + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetViewfinderImage); + ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image, NULL); + if (ret==PTP_RC_OK) + *size=ptp.Param1; return ret; } @@ -2738,20 +2696,15 @@ ptp_canon_getviewfinderimage (PTPParams* uint16_t ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum) { - uint16_t ret; - PTPContainer ptp; - unsigned char* data=NULL; - unsigned int len; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetChanges; - ptp.Nparam=0; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len); - if (ret == PTP_RC_OK) - *propnum=ptp_unpack_uint16_t_array(params,data,0,props); + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetChanges); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + *propnum=ptp_unpack_uint16_t_array(params,data,0,size,props); free(data); - return ret; + return PTP_RC_OK; } /** @@ -2782,34 +2735,42 @@ ptp_canon_getobjectinfo (PTPParams* para uint32_t parent, uint32_t handle, PTPCANONFolderEntry** entries, uint32_t* entnum) { - uint16_t ret; - PTPContainer ptp; - unsigned char *data = NULL; - unsigned int len; + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + unsigned int i, size; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_GetObjectInfoEx; - ptp.Param1=store; - ptp.Param2=p2; - ptp.Param3=parent; - ptp.Param4=handle; - ptp.Nparam=4; - len=0; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len); - if (ret == PTP_RC_OK) { - unsigned int i; - *entnum=ptp.Param1; - *entries=calloc(*entnum, sizeof(PTPCANONFolderEntry)); - if (*entries!=NULL) { - for(i=0; i<(*entnum); i++) - ptp_unpack_Canon_FE(params, - data+i*PTP_CANON_FolderEntryLen, - &((*entries)[i]) ); - } else { - ret=PTP_ERROR_IO; /* Cannot allocate memory */ - } + *entnum = 0; + *entries = NULL; + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetObjectInfoEx, store, p2, parent, handle); + data = NULL; + size = 0; + ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL); + if (ret != PTP_RC_OK) + goto exit; + if (!data) + return ret; + if (ptp.Param1 > size/PTP_CANON_FolderEntryLen) { + ptp_debug (params, "param1 is %d, size is only %d", ptp.Param1, size); + ret = PTP_RC_GeneralError; + goto exit; + } + + *entnum = ptp.Param1; + *entries= calloc(*entnum, sizeof(PTPCANONFolderEntry)); + if (*entries == NULL) { + ret = PTP_RC_GeneralError; + goto exit; + } + for(i=0; i<(*entnum); i++) { + if (size < i*PTP_CANON_FolderEntryLen) break; + ptp_unpack_Canon_FE(params, + data+i*PTP_CANON_FolderEntryLen, + &((*entries)[i]) ); } - free(data); + +exit: + free (data); return ret; } @@ -2833,16 +2794,14 @@ ptp_canon_getobjectinfo (PTPParams* para uint16_t ptp_canon_get_objecthandle_by_name (PTPParams* params, char* name, uint32_t* objectid) { - uint16_t ret; - PTPContainer ptp; - unsigned char *data = NULL; - uint8_t len; + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + uint8_t len = 0; - PTP_CNT_INIT (ptp); - ptp.Code=PTP_OC_CANON_GetObjectHandleByName; - ptp.Nparam=0; - len=0; + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetObjectHandleByName); data = malloc (2*(strlen(name)+1)+2); + if (!data) return PTP_RC_GeneralError; memset (data, 0, 2*(strlen(name)+1)+2); ptp_pack_string (params, name, data, 0, &len); ret=ptp_transaction (params, &ptp, PTP_DP_SENDDATA, (len+1)*2+1, &data, NULL); @@ -2871,24 +2830,17 @@ ptp_canon_get_customize_data (PTPParams* { PTPContainer ptp; - *data = NULL; - *size = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_CANON_GetCustomizeData; - ptp.Param1 = themenr; - ptp.Nparam = 1; + PTP_CNT_INIT(ptp, PTP_OC_CANON_GetCustomizeData, themenr); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } uint16_t -ptp_nikon_curve_download (PTPParams* params, unsigned char **data, unsigned int *size) { +ptp_nikon_curve_download (PTPParams* params, unsigned char **data, unsigned int *size) +{ PTPContainer ptp; - *data = NULL; - *size = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_NIKON_CurveDownload; - ptp.Nparam = 0; + + PTP_CNT_INIT(ptp, PTP_OC_NIKON_CurveDownload); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -2903,21 +2855,15 @@ ptp_nikon_curve_download (PTPParams* par * **/ uint16_t -ptp_sony_sdioconnect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3) { +ptp_sony_sdioconnect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3) +{ PTPContainer ptp; - uint16_t ret; - unsigned char *xdata = NULL; - unsigned int xsize; + unsigned char *data; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_SDIOConnect; - ptp.Nparam = 3; - ptp.Param1 = p1; - ptp.Param2 = p2; - ptp.Param3 = p3; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize); - free (xdata); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_SONY_SDIOConnect, p1, p2, p3); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL)); + free (data); + return PTP_RC_OK; } /** * ptp_sony_get_vendorpropcodes: @@ -2932,42 +2878,58 @@ ptp_sony_sdioconnect (PTPParams* params, * **/ uint16_t -ptp_sony_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) { +ptp_sony_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) +{ PTPContainer ptp; - uint16_t ret; unsigned char *xdata = NULL; - unsigned int xsize; + unsigned int xsize, psize1 = 0, psize2 = 0; + uint16_t *props1 = NULL,*props2 = NULL; *props = NULL; *size = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_GetSDIOGetExtDeviceInfo; - ptp.Nparam = 1; - ptp.Param1 = 0xc8; /* unclear */ - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize); - /* first 16 bit is 0xc8 0x00, then an array of 16 bit PTP ids */ - if (ret == PTP_RC_OK) - *size = ptp_unpack_uint16_t_array(params,xdata+2,0,props); + PTP_CNT_INIT(ptp, PTP_OC_SONY_GetSDIOGetExtDeviceInfo, 0xc8 /* unclear */); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize)); + if (xsize == 0) { + ptp_debug (params, "No special operations sent?"); + return PTP_RC_OK; + } + + psize1 = ptp_unpack_uint16_t_array (params, xdata+2, 0, xsize, &props1); + ptp_debug (params, "xsize %d, got size %d\n", xsize, psize1*2 + 2 + 4); + if (psize1*2 + 2 + 4 < xsize) { + psize2 = ptp_unpack_uint16_t_array(params,xdata+2+psize1*2+4, 0, xsize, &props2); + } + *props = calloc(psize1+psize2, sizeof(uint16_t)); + if (!*props) { + ptp_debug (params, "oom during malloc?"); + free (props1); + free (props2); + free (xdata); + return PTP_RC_OK; + } + *size = psize1+psize2; + memcpy (*props, props1, psize1*sizeof(uint16_t)); + memcpy ((*props)+psize1, props2, psize2*sizeof(uint16_t)); + free (props1); + free (props2); free (xdata); - return ret; + return PTP_RC_OK; } uint16_t -ptp_sony_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *dpd) { +ptp_sony_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *dpd) +{ PTPContainer ptp; + unsigned char *data; + unsigned int size, len = 0; uint16_t ret; - unsigned char *xdata = NULL; - unsigned int xsize,len = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_GetDevicePropdesc; - ptp.Nparam = 1; - ptp.Param1 = propcode; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize); + PTP_CNT_INIT(ptp, PTP_OC_SONY_GetDevicePropdesc, propcode); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data) return PTP_RC_GeneralError; /* first 16 bit is 0xc8 0x00, then an array of 16 bit PTP ids */ - if (ret == PTP_RC_OK) - ret = ptp_unpack_Sony_DPD(params,xdata,dpd,xsize,&len)?PTP_RC_OK:PTP_RC_GeneralError; - free (xdata); + ret = ptp_unpack_Sony_DPD(params,data,dpd,size,&len) ? PTP_RC_OK : PTP_RC_GeneralError; + free (data); return ret; } @@ -2975,17 +2937,18 @@ uint16_t ptp_sony_getalldevicepropdesc (PTPParams* params) { PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL , *dpddata; - uint32_t size = 0, readlen; + unsigned char *data, *dpddata; + unsigned int size, readlen; PTPDevicePropDesc dpd; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_GetAllDevicePropData; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret != PTP_RC_OK) - return ret; + PTP_CNT_INIT(ptp, PTP_OC_SONY_GetAllDevicePropData); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data) + return PTP_RC_GeneralError; + if (size <= 8) { + free (data); + return PTP_RC_GeneralError; + } dpddata = data+8; /* nr of entries 32bit, 0 32bit */ size -= 8; while (size>0) { @@ -3001,11 +2964,37 @@ ptp_sony_getalldevicepropdesc (PTPParams if (params->deviceproperties[i].desc.DevicePropertyCode == propcode) break; + /* debug output to see what changes */ + if (i != params->nrofdeviceproperties) { + switch (dpd.DataType) { + case PTP_DTC_INT8: +#define CHECK_CHANGED(type) \ + if (params->deviceproperties[i].desc.CurrentValue.type != dpd.CurrentValue.type) \ + ptp_debug (params, "ptp_sony_getalldevicepropdesc: %04x: value %d -> %d", propcode, params->deviceproperties[i].desc.CurrentValue.type, dpd.CurrentValue.type); + CHECK_CHANGED(i8); + break; + case PTP_DTC_UINT8: + CHECK_CHANGED(u8); + break; + case PTP_DTC_UINT16: + CHECK_CHANGED(u16); + break; + case PTP_DTC_INT16: + CHECK_CHANGED(i16); + break; + case PTP_DTC_INT32: + CHECK_CHANGED(i32); + break; + case PTP_DTC_UINT32: + CHECK_CHANGED(u32); + break; + default: + break; + } + } + if (i == params->nrofdeviceproperties) { - if (!i) - params->deviceproperties = malloc(sizeof(params->deviceproperties[0])); - else - params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); + params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); memset(¶ms->deviceproperties[i],0,sizeof(params->deviceproperties[0])); params->nrofdeviceproperties++; } else { @@ -3042,25 +3031,22 @@ ptp_sony_getalldevicepropdesc (PTPParams size -= readlen; } free(data); - return ret; + return PTP_RC_OK; } uint16_t ptp_sony_setdevicecontrolvaluea (PTPParams* params, uint16_t propcode, PTPPropertyValue *value, uint16_t datatype) { - PTPContainer ptp; - uint16_t ret; - uint32_t size; - unsigned char* dpv=NULL; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_SetControlDeviceA; - ptp.Param1 = propcode; - ptp.Nparam = 1; - size = ptp_pack_DPV(params, value, &dpv, datatype); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL); - free(dpv); + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_SONY_SetControlDeviceA, propcode); + size = ptp_pack_DPV(params, value, &data, datatype); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); return ret; } @@ -3068,18 +3054,53 @@ uint16_t ptp_sony_setdevicecontrolvalueb (PTPParams* params, uint16_t propcode, PTPPropertyValue *value, uint16_t datatype) { - PTPContainer ptp; - uint16_t ret; - uint32_t size; - unsigned char* dpv=NULL; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_SONY_SetControlDeviceB; - ptp.Param1 = propcode; - ptp.Nparam = 1; - size = ptp_pack_DPV(params, value, &dpv, datatype); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL); - free(dpv); + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_SONY_SetControlDeviceB, propcode); + size = ptp_pack_DPV(params, value, &data , datatype); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); + return ret; +} + +uint16_t +ptp_sony_9280 (PTPParams* params, uint32_t param1, + uint32_t additional, uint32_t data2, uint32_t data3, uint32_t data4, uint8_t x, uint8_t y) +{ + PTPContainer ptp; + unsigned char buf[18]; + unsigned char *buffer; + + PTP_CNT_INIT(ptp, 0x9280, param1); + + if ((additional != 0) && (additional != 2)) + return PTP_RC_GeneralError; + + htod32a(&buf[0], additional); + htod32a(&buf[4], data2); + htod32a(&buf[8], data3); + htod32a(&buf[12], data4); + + /* only sent in the case where additional is 2 */ + buf[16]= x; buf[17]= y; + + buffer=buf; + return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 16+additional, &buffer, NULL); +} + +uint16_t +ptp_sony_9281 (PTPParams* params, uint32_t param1) { + PTPContainer ptp; + unsigned int size = 0; + unsigned char *buffer = NULL; + uint16_t ret; + + PTP_CNT_INIT(ptp, 0x9281, param1); + ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &buffer, &size); + free (buffer); return ret; } @@ -3098,30 +3119,25 @@ ptp_sony_setdevicecontrolvalueb (PTPPara * **/ /* Cache time in seconds. Should perhaps be more granular... */ -#define CACHETIME 2 uint16_t ptp_generic_getdevicepropdesc (PTPParams *params, uint16_t propcode, PTPDevicePropDesc *dpd) { unsigned int i; - uint16_t ret; time_t now; for (i=0;i<params->nrofdeviceproperties;i++) if (params->deviceproperties[i].desc.DevicePropertyCode == propcode) break; if (i == params->nrofdeviceproperties) { - if (!i) - params->deviceproperties = malloc(sizeof(params->deviceproperties[0])); - else - params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); + params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0])); memset(¶ms->deviceproperties[i],0,sizeof(params->deviceproperties[0])); params->nrofdeviceproperties++; } if (params->deviceproperties[i].desc.DataType != PTP_DTC_UNDEF) { time(&now); - if ((now - params->deviceproperties[i].timestamp) <= CACHETIME) { + if (params->deviceproperties[i].timestamp + params->cachetime > now) { duplicate_DevicePropDesc(¶ms->deviceproperties[i].desc, dpd); return PTP_RC_OK; } @@ -3132,13 +3148,15 @@ ptp_generic_getdevicepropdesc (PTPParams if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) && ptp_operation_issupported(params, PTP_OC_SONY_GetAllDevicePropData) ) { - ret = ptp_sony_getalldevicepropdesc (params); - if (ret != PTP_RC_OK) - return ret; + CHECK_PTP_RC(ptp_sony_getalldevicepropdesc (params)); for (i=0;i<params->nrofdeviceproperties;i++) if (params->deviceproperties[i].desc.DevicePropertyCode == propcode) break; + if (i == params->nrofdeviceproperties) { + ptp_debug (params, "property 0x%04x not found?\n", propcode); + return PTP_RC_GeneralError; + } time(&now); params->deviceproperties[i].timestamp = now; duplicate_DevicePropDesc(¶ms->deviceproperties[i].desc, dpd); @@ -3147,9 +3165,7 @@ ptp_generic_getdevicepropdesc (PTPParams if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) && ptp_operation_issupported(params, PTP_OC_SONY_GetDevicePropdesc) ) { - ret = ptp_sony_getdevicepropdesc (params, propcode, ¶ms->deviceproperties[i].desc); - if (ret != PTP_RC_OK) - return ret; + CHECK_PTP_RC(ptp_sony_getdevicepropdesc (params, propcode, ¶ms->deviceproperties[i].desc)); time(&now); params->deviceproperties[i].timestamp = now; @@ -3159,9 +3175,7 @@ ptp_generic_getdevicepropdesc (PTPParams if (ptp_operation_issupported(params, PTP_OC_GetDevicePropDesc)) { - ret = ptp_getdevicepropdesc (params, propcode, ¶ms->deviceproperties[i].desc); - if (ret != PTP_RC_OK) - return ret; + CHECK_PTP_RC(ptp_getdevicepropdesc (params, propcode, ¶ms->deviceproperties[i].desc)); time(&now); params->deviceproperties[i].timestamp = now; @@ -3189,9 +3203,19 @@ uint16_t ptp_generic_setdevicepropvalue (PTPParams* params, uint16_t propcode, PTPPropertyValue *value, uint16_t datatype) { + unsigned int i; + + /* reset the cache entry */ + for (i=0;i<params->nrofdeviceproperties;i++) + if (params->deviceproperties[i].desc.DevicePropertyCode == propcode) + break; + if (i != params->nrofdeviceproperties) + params->deviceproperties[i].timestamp = 0; + /* FIXME: change the cache? hmm */ + /* this works for some methods, but not for all */ if ( (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) && - ptp_operation_issupported(params, PTP_OC_SONY_SetControlDeviceB) + ptp_operation_issupported(params, PTP_OC_SONY_SetControlDeviceA) ) return ptp_sony_setdevicecontrolvaluea (params, propcode, value, datatype); return ptp_setdevicepropvalue (params, propcode, value, datatype); @@ -3210,22 +3234,19 @@ ptp_generic_setdevicepropvalue (PTPParam * **/ uint16_t -ptp_nikon_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) { +ptp_nikon_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) +{ PTPContainer ptp; - uint16_t ret; - unsigned char *xdata = NULL; - unsigned int xsize; + unsigned char *data = NULL; + unsigned int xsize = 0; *props = NULL; *size = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_NIKON_GetVendorPropCodes; - ptp.Nparam = 0; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize); - if (ret == PTP_RC_OK) - *size = ptp_unpack_uint16_t_array(params,xdata,0,props); - free (xdata); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetVendorPropCodes); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &xsize)); + *size = ptp_unpack_uint16_t_array(params,data,0,xsize,props); + free (data); + return PTP_RC_OK; } uint16_t @@ -3234,14 +3255,8 @@ ptp_nikon_getfileinfoinblock ( PTPParams unsigned char **data, unsigned int *size ) { PTPContainer ptp; - *data = NULL; - *size = 0; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_NIKON_GetFileInfoInBlock; - ptp.Nparam = 3; - ptp.Param1 = p1; - ptp.Param2 = p2; - ptp.Param3 = p3; + + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetFileInfoInBlock, p1, p2, p3); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -3260,9 +3275,7 @@ ptp_nikon_get_liveview_image (PTPParams* { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_GetLiveViewImg; - ptp.Nparam=0; + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetLiveViewImg); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -3280,22 +3293,18 @@ uint16_t ptp_nikon_get_preview_image (PTPParams* params, unsigned char **xdata, unsigned int *xsize, uint32_t *handle) { - PTPContainer ptp; - uint16_t ret; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_GetPreviewImg; - ptp.Nparam=0; + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetPreviewImg); + /* FIXME: * pdslrdashboard passes 3 parameters: * objectid, minimum size, maximum size */ - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, xdata, xsize); - if (ret == PTP_RC_OK) { - if (ptp.Nparam > 0) - *handle = ptp.Param1; - } - return ret; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, xdata, xsize)); + if (ptp.Nparam > 0) + *handle = ptp.Param1; + return PTP_RC_OK; } /** @@ -3313,10 +3322,7 @@ ptp_canon_eos_get_viewfinder_image (PTPP { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_EOS_GetViewFinderData; - ptp.Nparam=1; - ptp.Param1=0x00100000; /* from trace */ + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetViewFinderData, 0x00100000 /* from trace */); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -3325,10 +3331,7 @@ ptp_canon_eos_get_viewfinder_image_handl { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CANON_EOS_GetViewFinderData; - ptp.Nparam=1; - ptp.Param1=0x00100000; /* from trace */ + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetViewFinderData, 0x00100000 /* from trace */); return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler); } @@ -3347,21 +3350,16 @@ ptp_canon_eos_get_viewfinder_image_handl uint16_t ptp_nikon_check_event (PTPParams* params, PTPContainer** event, unsigned int* evtcnt) { - PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL; - unsigned int size = 0; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_CheckEvent; - ptp.Nparam=0; + PTPContainer ptp; + unsigned char *data; + unsigned int size; + + PTP_CNT_INIT(ptp, PTP_OC_NIKON_CheckEvent); *evtcnt = 0; - ret = ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret == PTP_RC_OK) { - ptp_unpack_Nikon_EC (params, data, size, event, evtcnt); - free (data); - } - return ret; + CHECK_PTP_RC(ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_Nikon_EC (params, data, size, event, evtcnt); + free (data); + return PTP_RC_OK; } /** @@ -3381,9 +3379,7 @@ ptp_nikon_getptpipinfo (PTPParams* param { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_GetDevicePTPIPInfo; - ptp.Nparam=0; + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetDevicePTPIPInfo); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); } @@ -3400,28 +3396,24 @@ ptp_nikon_getptpipinfo (PTPParams* param uint16_t ptp_nikon_getwifiprofilelist (PTPParams* params) { - PTPContainer ptp; - unsigned char* data; - unsigned int size; - unsigned int pos; - unsigned int profn; - unsigned int n; - char* buffer; - uint8_t len; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_GetProfileAllData; - ptp.Nparam=0; - size = 0; - data = NULL; + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + unsigned int size, pos, profn, n; + char *buffer; + uint8_t len; + + PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetProfileAllData); CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); - if (size < 2) return PTP_RC_Undefined; /* FIXME: Add more precise error code */ + ret = PTP_RC_Undefined; /* FIXME: Add more precise error code */ + + if (size < 2) + goto exit; params->wifi_profiles_version = data[0]; params->wifi_profiles_number = data[1]; - if (params->wifi_profiles) - free(params->wifi_profiles); + free(params->wifi_profiles); params->wifi_profiles = malloc(params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile)); memset(params->wifi_profiles, 0, params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile)); @@ -3429,13 +3421,15 @@ ptp_nikon_getwifiprofilelist (PTPParams* pos = 2; profn = 0; while (profn < params->wifi_profiles_number && pos < size) { - if (pos+6 >= size) return PTP_RC_Undefined; + if (pos+6 >= size) + goto exit; params->wifi_profiles[profn].id = data[pos++]; params->wifi_profiles[profn].valid = data[pos++]; n = dtoh32a(&data[pos]); pos += 4; - if (pos+n+4 >= size) return PTP_RC_Undefined; + if (pos+n+4 >= size) + goto exit; strncpy(params->wifi_profiles[profn].profile_name, (char*)&data[pos], n); params->wifi_profiles[profn].profile_name[16] = '\0'; pos += n; @@ -3444,21 +3438,24 @@ ptp_nikon_getwifiprofilelist (PTPParams* params->wifi_profiles[profn].device_type = data[pos++]; params->wifi_profiles[profn].icon_type = data[pos++]; - buffer = ptp_unpack_string(params, data, pos, &len); + buffer = ptp_unpack_string(params, data, pos, size, &len); strncpy(params->wifi_profiles[profn].creation_date, buffer, sizeof(params->wifi_profiles[profn].creation_date)); free (buffer); pos += (len*2+1); - if (pos+1 >= size) return PTP_RC_Undefined; + if (pos+1 >= size) + goto exit; /* FIXME: check if it is really last usage date */ - buffer = ptp_unpack_string(params, data, pos, &len); + buffer = ptp_unpack_string(params, data, pos, size, &len); strncpy(params->wifi_profiles[profn].lastusage_date, buffer, sizeof(params->wifi_profiles[profn].lastusage_date)); free (buffer); pos += (len*2+1); - if (pos+5 >= size) return PTP_RC_Undefined; + if (pos+5 >= size) + goto exit; n = dtoh32a(&data[pos]); pos += 4; - if (pos+n >= size) return PTP_RC_Undefined; + if (pos+n >= size) + goto exit; strncpy(params->wifi_profiles[profn].essid, (char*)&data[pos], n); params->wifi_profiles[profn].essid[32] = '\0'; pos += n; @@ -3480,8 +3477,11 @@ ptp_nikon_getwifiprofilelist (PTPParams* ptp_nikon_writewifiprofile(params, &test); #endif - - return PTP_RC_OK; + /* everything went Ok */ + ret = PTP_RC_OK; +exit: + free (data); + return ret; } /** @@ -3500,8 +3500,6 @@ ptp_nikon_getwifiprofilelist (PTPParams* uint16_t ptp_nikon_writewifiprofile (PTPParams* params, PTPNIKONWifiProfile* profile) { - unsigned char guid[16]; - PTPContainer ptp; unsigned char buffer[1024]; unsigned char* data = buffer; @@ -3509,7 +3507,8 @@ ptp_nikon_writewifiprofile (PTPParams* p int i; uint8_t len; int profilenr = -1; - + unsigned char guid[16]; + ptp_nikon_getptpipguid(guid); if (!params->wifi_profiles) @@ -3580,10 +3579,7 @@ ptp_nikon_writewifiprofile (PTPParams* p } size = 0xC4; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_NIKON_SendProfileData; - ptp.Nparam=1; - ptp.Param1=profilenr; + PTP_CNT_INIT(ptp, PTP_OC_NIKON_SendProfileData, profilenr); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); } @@ -3604,20 +3600,16 @@ uint16_t ptp_mtp_getobjectpropssupported (PTPParams* params, uint16_t ofc, uint32_t *propnum, uint16_t **props ) { - PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL; - unsigned int size = 0; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_GetObjectPropsSupported; - ptp.Nparam = 1; - ptp.Param1 = ofc; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret == PTP_RC_OK) - *propnum=ptp_unpack_uint16_t_array(params,data,0,props); + PTPContainer ptp; + unsigned char *data = NULL; + unsigned int xsize = 0; + + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropsSupported, ofc); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &xsize)); + if (!data) return PTP_RC_GeneralError; + *propnum=ptp_unpack_uint16_t_array (params, data, 0, xsize, props); free(data); - return ret; + return PTP_RC_OK; } /** @@ -3636,21 +3628,15 @@ uint16_t ptp_mtp_getobjectpropdesc ( PTPParams* params, uint16_t opc, uint16_t ofc, PTPObjectPropDesc *opd ) { - PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL; - unsigned int size = 0; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_GetObjectPropDesc; - ptp.Nparam = 2; - ptp.Param1 = opc; - ptp.Param2 = ofc; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret == PTP_RC_OK) - ptp_unpack_OPD (params, data, opd, size); + PTPContainer ptp; + unsigned char *data; + unsigned int size; + + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropDesc, opc, ofc); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_OPD (params, data, opd, size); free(data); - return ret; + return PTP_RC_OK; } /** @@ -3670,25 +3656,17 @@ ptp_mtp_getobjectpropvalue ( PTPParams* params, uint32_t oid, uint16_t opc, PTPPropertyValue *value, uint16_t datatype ) { - PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL; - unsigned int size = 0; - unsigned int offset = 0; + PTPContainer ptp; + uint16_t ret = PTP_RC_OK; + unsigned char *data; + unsigned int size, offset = 0; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_GetObjectPropValue; - ptp.Nparam = 2; - ptp.Param1 = oid; - ptp.Param2 = opc; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size); - if (ret == PTP_RC_OK) { - int ret2 = ptp_unpack_DPV(params, data, &offset, size, value, datatype); - if (!ret2) { - ptp_debug (params, "ptp_mtp_getobjectpropvalue: unpacking DPV failed"); - ret = PTP_RC_GeneralError; - } - } + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropValue, oid, opc); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!ptp_unpack_DPV(params, data, &offset, size, value, datatype)) { + ptp_debug (params, "ptp_mtp_getobjectpropvalue: unpacking DPV failed"); + ret = PTP_RC_GeneralError; + } free(data); return ret; } @@ -3710,16 +3688,12 @@ ptp_mtp_setobjectpropvalue ( PTPParams* params, uint32_t oid, uint16_t opc, PTPPropertyValue *value, uint16_t datatype ) { - PTPContainer ptp; - uint16_t ret; - unsigned char *data = NULL; - unsigned int size ; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_SetObjectPropValue; - ptp.Nparam = 2; - ptp.Param1 = oid; - ptp.Param2 = opc; + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjectPropValue, oid, opc); size = ptp_pack_DPV(params, value, &data, datatype); ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); free(data); @@ -3729,116 +3703,94 @@ ptp_mtp_setobjectpropvalue ( uint16_t ptp_mtp_getobjectreferences (PTPParams* params, uint32_t handle, uint32_t** ohArray, uint32_t* arraylen) { - PTPContainer ptp; - uint16_t ret; - unsigned char* dpv=NULL; - unsigned int dpvlen = 0; - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_GetObjectReferences; - ptp.Param1=handle; - ptp.Nparam=1; - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &dpvlen); - if (ret == PTP_RC_OK) { - /* Sandisk Sansa skips the DATA phase, but returns OK as response. + PTPContainer ptp; + unsigned char *data; + unsigned int size; + + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectReferences, handle); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data , &size)); + /* Sandisk Sansa skips the DATA phase, but returns OK as response. * this will gives us a NULL here. Handle it. -Marcus */ - if ((dpv == NULL) || (dpvlen == 0)) { - *arraylen = 0; - *ohArray = NULL; - } else { - *arraylen = ptp_unpack_uint32_t_array(params, dpv, 0, ohArray); - } + if ((data == NULL) || (size == 0)) { + *arraylen = 0; + *ohArray = NULL; + } else { + *arraylen = ptp_unpack_uint32_t_array(params, data , 0, size, ohArray); } - free(dpv); - return ret; + free(data); + return PTP_RC_OK; } uint16_t ptp_mtp_setobjectreferences (PTPParams* params, uint32_t handle, uint32_t* ohArray, uint32_t arraylen) { - PTPContainer ptp; - uint16_t ret; - uint32_t size; - unsigned char* dpv=NULL; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_SetObjectReferences; - ptp.Param1 = handle; - ptp.Nparam = 1; - size = ptp_pack_uint32_t_array(params, ohArray, arraylen, &dpv); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char **)&dpv, NULL); - free(dpv); + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; + + PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjectReferences, handle); + size = ptp_pack_uint32_t_array(params, ohArray, arraylen, &data); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); return ret; } uint16_t ptp_mtp_getobjectproplist (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops) { - uint16_t ret; - PTPContainer ptp; - unsigned char* opldata = NULL; - unsigned int oplsize; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_GetObjPropList; - ptp.Param1 = handle; - ptp.Param2 = 0x00000000U; /* 0x00000000U should be "all formats" */ - ptp.Param3 = 0xFFFFFFFFU; /* 0xFFFFFFFFU should be "all properties" */ - ptp.Param4 = 0x00000000U; - ptp.Param5 = 0xFFFFFFFFU; /* means - return full tree below the Param1 handle */ - ptp.Nparam = 5; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &opldata, &oplsize); - if (ret == PTP_RC_OK) *nrofprops = ptp_unpack_OPL(params, opldata, props, oplsize); - if (opldata != NULL) - free(opldata); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjPropList, handle, + 0x00000000U, /* 0x00000000U should be "all formats" */ + 0xFFFFFFFFU, /* 0xFFFFFFFFU should be "all properties" */ + 0x00000000U, + 0xFFFFFFFFU /* means - return full tree below the Param1 handle */ + ); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + *nrofprops = ptp_unpack_OPL(params, data, props, size); + free(data); + return PTP_RC_OK; } uint16_t ptp_mtp_getobjectproplist_single (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops) { - uint16_t ret; - PTPContainer ptp; - unsigned char* opldata = NULL; - unsigned int oplsize; + PTPContainer ptp; + unsigned char *data; + unsigned int size; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_GetObjPropList; - ptp.Param1 = handle; - ptp.Param2 = 0x00000000U; /* 0x00000000U should be "all formats" */ - ptp.Param3 = 0xFFFFFFFFU; /* 0xFFFFFFFFU should be "all properties" */ - ptp.Param4 = 0x00000000U; - ptp.Param5 = 0x00000000U; /* means - return single tree below the Param1 handle */ - ptp.Nparam = 5; - ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &opldata, &oplsize); - if (ret == PTP_RC_OK) *nrofprops = ptp_unpack_OPL(params, opldata, props, oplsize); - if (opldata != NULL) - free(opldata); - return ret; + PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjPropList, handle, + 0x00000000U, /* 0x00000000U should be "all formats" */ + 0xFFFFFFFFU, /* 0xFFFFFFFFU should be "all properties" */ + 0x00000000U, + 0x00000000U /* means - return single tree below the Param1 handle */ + ); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + *nrofprops = ptp_unpack_OPL(params, data, props, size); + free(data); + return PTP_RC_OK; } uint16_t ptp_mtp_sendobjectproplist (PTPParams* params, uint32_t* store, uint32_t* parenthandle, uint32_t* handle, uint16_t objecttype, uint64_t objectsize, MTPProperties *props, int nrofprops) { - uint16_t ret; - PTPContainer ptp; - unsigned char* opldata=NULL; - uint32_t oplsize; + PTPContainer ptp; + uint16_t ret; + unsigned char *data = NULL; + uint32_t size; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_SendObjectPropList; - ptp.Param1 = *store; - ptp.Param2 = *parenthandle; - ptp.Param3 = (uint32_t) objecttype; - ptp.Param4 = (uint32_t) (objectsize >> 32); - ptp.Param5 = (uint32_t) (objectsize & 0xffffffffU); - ptp.Nparam = 5; + PTP_CNT_INIT(ptp, PTP_OC_MTP_SendObjectPropList, *store, *parenthandle, (uint32_t) objecttype, + (uint32_t) (objectsize >> 32), (uint32_t) (objectsize & 0xffffffffU) + ); /* Set object handle to 0 for a new object */ - oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL); - free(opldata); + size = ptp_pack_OPL(params,props,nrofprops,&data); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); *store = ptp.Param1; *parenthandle = ptp.Param2; *handle = ptp.Param3; @@ -3849,20 +3801,15 @@ ptp_mtp_sendobjectproplist (PTPParams* p uint16_t ptp_mtp_setobjectproplist (PTPParams* params, MTPProperties *props, int nrofprops) { - uint16_t ret; - PTPContainer ptp; - unsigned char* opldata=NULL; - uint32_t oplsize; - - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_SetObjPropList; - ptp.Nparam = 0; - - oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata); - ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL); - free(opldata); + PTPContainer ptp; + unsigned char *data = NULL; + uint32_t size; - return ret; + PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjPropList); + size = ptp_pack_OPL(params,props,nrofprops,&data); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL)); + free(data); + return PTP_RC_OK; } uint16_t @@ -3870,8 +3817,7 @@ ptp_mtpz_sendwmdrmpdapprequest (PTPParam { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest; + PTP_CNT_INIT(ptp, PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest); return ptp_transaction (params, &ptp, PTP_DP_SENDDATA, size, &appcertmsg, NULL); } @@ -3880,8 +3826,7 @@ ptp_mtpz_getwmdrmpdappresponse (PTPParam { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code = PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse; + PTP_CNT_INIT(ptp, PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse); *size = 0; *response = NULL; return ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, response, size); @@ -3894,12 +3839,7 @@ ptp_chdk_get_memory(PTPParams* params, i { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=3; - ptp.Param1=PTP_CHDK_GetMemory; - ptp.Param2=start; - ptp.Param3=num; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_GetMemory, start, num); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, buf, NULL); } @@ -3909,15 +3849,22 @@ ptp_chdk_set_memory_long(PTPParams* para PTPContainer ptp; unsigned char *buf = (unsigned char *) &val; /* FIXME ... endianness? */ - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=3; - ptp.Param1=PTP_CHDK_SetMemory; - ptp.Param2=addr; - ptp.Param3=4; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_SetMemory, addr, 4); return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 4, &buf, NULL); } +uint16_t +ptp_chdk_download(PTPParams* params, char *remote_fn, PTPDataHandler *handler) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_TempData, 0); + CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(remote_fn), (unsigned char**)&remote_fn, NULL)); + + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_DownloadFile); + return ptp_transaction_new (params, &ptp, PTP_DP_GETDATA, 0, handler); +} + #if 0 int ptp_chdk_upload(PTPParams* params, char *local_fn, char *remote_fn) { @@ -3927,10 +3874,7 @@ int ptp_chdk_upload(PTPParams* params, c FILE *f; unsigned file_len,data_len,file_name_len; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_UploadFile; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_UploadFile); f = fopen(local_fn,"rb"); if ( f == NULL ) @@ -3964,62 +3908,6 @@ int ptp_chdk_upload(PTPParams* params, c return 1; } -static uint16_t gd_to_file(PTPParams* params, PTPGetdataParams *gdparams, unsigned len, unsigned char *bytes) { - FILE *f = (FILE *)gdparams->handler_data; - size_t count=fwrite(bytes,1,len,f); - if(count != len) { - return PTP_ERROR_IO; - } - return PTP_RC_OK; -} - -int ptp_chdk_download(PTPParams* params, char *remote_fn, char *local_fn) -{ - uint16_t ret; - PTPContainer ptp; - PTPGetdataParams gdparams; - FILE *f; - - f = fopen(local_fn,"wb"); - if ( f == NULL ) - { - ptp_error(params,"could not open file \'%s\'",local_fn); - return 0; - } - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=2; - ptp.Param1=PTP_CHDK_TempData; - ptp.Param2=0; - ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(remote_fn), &remote_fn, NULL); - if ( ret != PTP_RC_OK ) - { - ptp_error(params,"unexpected return code 0x%x",ret); - fclose(f); - return 0; - } - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_DownloadFile; - - PTP_CNT_INIT(gdparams); - - gdparams.handler = gd_to_file; - gdparams.block_size = 0; // default - gdparams.handler_data = f; - ret=ptp_getdata_transaction(params, &ptp, &gdparams); - fclose(f); - if ( ret != PTP_RC_OK ) - { - ptp_error(params,"unexpected return code 0x%x",ret); - return 0; - } - - return 1; -} #endif /* @@ -4032,173 +3920,115 @@ int ptp_chdk_download(PTPParams* params, uint16_t ptp_chdk_rcisready(PTPParams* params, int *isready, int *imgnum) { - uint16_t ret; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_RemoteCaptureIsReady; - - ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ( ret != PTP_RC_OK ) - return ret; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_RemoteCaptureIsReady); + *isready = *imgnum = 0; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *isready=ptp.Param1; *imgnum=ptp.Param2; - return ret; + return PTP_RC_OK; } uint16_t ptp_chdk_rcgetchunk(PTPParams* params, int fmt, ptp_chdk_rc_chunk *chunk) { - uint16_t ret; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=2; - ptp.Param1=PTP_CHDK_RemoteCaptureGetData; - ptp.Param2=fmt; //get chunk + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_RemoteCaptureGetData, fmt); //get chunk chunk->data = NULL; chunk->size = 0; chunk->offset = 0; chunk->last = 0; - // TODO should allow ptp_getdata_transaction to send chunks directly to file, or to mem - ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &chunk->data, NULL); - if ( ret != PTP_RC_OK ) - return ret; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &chunk->data, NULL)); chunk->size = ptp.Param1; chunk->last = (ptp.Param2 == 0); chunk->offset = ptp.Param3; //-1 for none - return ret; + return PTP_RC_OK; } uint16_t ptp_chdk_exec_lua(PTPParams* params, char *script, int flags, int *script_id, int *status) { - uint16_t r; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=2; - ptp.Param1=PTP_CHDK_ExecuteScript; - ptp.Param2=PTP_CHDK_SL_LUA | flags; - - r = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(script)+1, (unsigned char**)&script, NULL); - - if ( r != PTP_RC_OK ) { - *script_id = 0; - *status = 0; - return r; - } else { - *script_id = ptp.Param1; - *status = ptp.Param2; - //return (*status == PTP_CHDK_S_ERRTYPE_NONE); - if (*status == PTP_CHDK_S_ERRTYPE_NONE) - return PTP_RC_OK; - else - return r; - } + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ExecuteScript, PTP_CHDK_SL_LUA | flags); + *script_id = 0; + *status = 0; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(script)+1, (unsigned char**)&script, NULL)); + *script_id = ptp.Param1; + *status = ptp.Param2; + return PTP_RC_OK; } uint16_t ptp_chdk_get_version(PTPParams* params, int *major, int *minor) { - uint16_t r; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_Version; - r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ( r != PTP_RC_OK ) - return r; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_Version); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *major = ptp.Param1; *minor = ptp.Param2; - return r; + return PTP_RC_OK; } uint16_t ptp_chdk_get_script_status(PTPParams* params, unsigned *status) { - uint16_t r; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_ScriptStatus; - r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ( r != PTP_RC_OK ) - return r; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ScriptStatus); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *status = ptp.Param1; - return r; + return PTP_RC_OK; } uint16_t ptp_chdk_get_script_support(PTPParams* params, unsigned *status) { - uint16_t r; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_ScriptSupport; - r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); - if ( r != PTP_RC_OK ) - return r; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ScriptSupport); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); *status = ptp.Param1; - return r; + return PTP_RC_OK; } uint16_t ptp_chdk_write_script_msg(PTPParams* params, char *data, unsigned size, int target_script_id, int *status) { - uint16_t r; PTPContainer ptp; // a zero length data phase appears to do bad things, camera stops responding to PTP if(!size) { ptp_error(params,"zero length message not allowed"); *status = 0; - return 0; - } - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=2; - ptp.Param1=PTP_CHDK_WriteScriptMsg; - ptp.Param2=target_script_id; - - r=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char**)&data, NULL); - if ( r != PTP_RC_OK ) { - *status = 0; - return r; + return PTP_ERROR_BADPARAM; } + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_WriteScriptMsg, target_script_id); + *status = 0; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char**)&data, NULL)); *status = ptp.Param1; - return r; + return PTP_RC_OK; } uint16_t ptp_chdk_read_script_msg(PTPParams* params, ptp_chdk_script_msg **msg) { - uint16_t r; - PTPContainer ptp; - unsigned char *data = NULL; + PTPContainer ptp; + unsigned char *data; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_ReadScriptMsg; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ReadScriptMsg); *msg = NULL; /* camera will always send data, otherwise getdata will cause problems */ - r=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL); - if ( r != PTP_RC_OK ) - return r; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL)); + if (!data) { + ptp_error(params,"no data received"); + return PTP_ERROR_BADPARAM; + } /* for convenience, always allocate an extra byte and null it*/ *msg = malloc(sizeof(ptp_chdk_script_msg) + ptp.Param4 + 1); @@ -4209,48 +4039,31 @@ ptp_chdk_read_script_msg(PTPParams* para memcpy((*msg)->data,data,(*msg)->size); (*msg)->data[(*msg)->size] = 0; free(data); - return r; + return PTP_RC_OK; } uint16_t -ptp_chdk_get_live_data(PTPParams* params, unsigned flags, unsigned char **data, unsigned int *data_size) { - uint16_t r; +ptp_chdk_get_live_data(PTPParams* params, unsigned flags, unsigned char **data, unsigned int *data_size) +{ PTPContainer ptp; - unsigned int real_size = 0; - - - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=2; - ptp.Param1=PTP_CHDK_GetDisplayData; - ptp.Param2=flags; - *data = NULL; + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_GetDisplayData, flags); *data_size = 0; - - r = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &real_size); - if ( r != PTP_RC_OK ) - return r; + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL)); *data_size = ptp.Param1; - return r; + return PTP_RC_OK; } uint16_t ptp_chdk_call_function(PTPParams* params, int *args, int size, int *ret) { - uint16_t r; PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_CHDK; - ptp.Nparam=1; - ptp.Param1=PTP_CHDK_CallFunction; - r=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size*sizeof(int), (unsigned char **) &args, NULL); - if ( r != PTP_RC_OK ) - return r; - if ( ret ) + PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_CallFunction); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size*sizeof(int), (unsigned char **) &args, NULL)); + if (ret) *ret = ptp.Param1; - return r; + return PTP_RC_OK; } @@ -4283,14 +4096,7 @@ ptp_android_getpartialobject64 (PTPParam { PTPContainer ptp; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_ANDROID_GetPartialObject64; - ptp.Param1=handle; - ptp.Param2=offset & 0xFFFFFFFF; - ptp.Param3=offset >> 32; - ptp.Param4=maxbytes; - ptp.Nparam=4; - *len=0; + PTP_CNT_INIT(ptp, PTP_OC_ANDROID_GetPartialObject64, handle, offset & 0xFFFFFFFF, offset >> 32, maxbytes); return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len); } @@ -4298,16 +4104,10 @@ uint16_t ptp_android_sendpartialobject (PTPParams* params, uint32_t handle, uint64_t offset, unsigned char* object, uint32_t len) { - uint32_t err; - PTPContainer ptp; + PTPContainer ptp; + uint16_t ret; - PTP_CNT_INIT(ptp); - ptp.Code=PTP_OC_ANDROID_SendPartialObject; - ptp.Param1=handle; - ptp.Param2=offset & 0xFFFFFFFF; - ptp.Param3=offset >> 32; - ptp.Param4=len; - ptp.Nparam=4; + PTP_CNT_INIT(ptp, PTP_OC_ANDROID_SendPartialObject, handle, offset & 0xFFFFFFFF, offset >> 32, len); /* * MtpServer.cpp is buggy: it uses write() without offset @@ -4315,10 +4115,10 @@ ptp_android_sendpartialobject (PTPParams * the header packet */ params->split_header_data = 1; - err=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, len, &object, NULL); + ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, len, &object, NULL); params->split_header_data = 0; - return err; + return ret; } @@ -4369,75 +4169,91 @@ ptp_free_object (PTPObject *ob) ob->flags = 0; } -const char * -ptp_strerror(uint16_t error) { +/* PTP error descriptions */ +static struct { + uint16_t rc; + uint16_t vendor; + const char *txt; +} ptp_errors[] = { + {PTP_RC_Undefined, 0, N_("PTP Undefined Error")}, + {PTP_RC_OK, 0, N_("PTP OK!")}, + {PTP_RC_GeneralError, 0, N_("PTP General Error")}, + {PTP_RC_SessionNotOpen, 0, N_("PTP Session Not Open")}, + {PTP_RC_InvalidTransactionID, 0, N_("PTP Invalid Transaction ID")}, + {PTP_RC_OperationNotSupported, 0, N_("PTP Operation Not Supported")}, + {PTP_RC_ParameterNotSupported, 0, N_("PTP Parameter Not Supported")}, + {PTP_RC_IncompleteTransfer, 0, N_("PTP Incomplete Transfer")}, + {PTP_RC_InvalidStorageId, 0, N_("PTP Invalid Storage ID")}, + {PTP_RC_InvalidObjectHandle, 0, N_("PTP Invalid Object Handle")}, + {PTP_RC_DevicePropNotSupported, 0, N_("PTP Device Prop Not Supported")}, + {PTP_RC_InvalidObjectFormatCode,0, N_("PTP Invalid Object Format Code")}, + {PTP_RC_StoreFull, 0, N_("PTP Store Full")}, + {PTP_RC_ObjectWriteProtected, 0, N_("PTP Object Write Protected")}, + {PTP_RC_StoreReadOnly, 0, N_("PTP Store Read Only")}, + {PTP_RC_AccessDenied, 0, N_("PTP Access Denied")}, + {PTP_RC_NoThumbnailPresent, 0, N_("PTP No Thumbnail Present")}, + {PTP_RC_SelfTestFailed, 0, N_("PTP Self Test Failed")}, + {PTP_RC_PartialDeletion, 0, N_("PTP Partial Deletion")}, + {PTP_RC_StoreNotAvailable, 0, N_("PTP Store Not Available")}, + {PTP_RC_SpecificationByFormatUnsupported, 0, N_("PTP Specification By Format Unsupported")}, + {PTP_RC_NoValidObjectInfo, 0, N_("PTP No Valid Object Info")}, + {PTP_RC_InvalidCodeFormat, 0, N_("PTP Invalid Code Format")}, + {PTP_RC_UnknownVendorCode, 0, N_("PTP Unknown Vendor Code")}, + {PTP_RC_CaptureAlreadyTerminated, 0, N_("PTP Capture Already Terminated")}, + {PTP_RC_DeviceBusy, 0, N_("PTP Device Busy")}, + {PTP_RC_InvalidParentObject, 0, N_("PTP Invalid Parent Object")}, + {PTP_RC_InvalidDevicePropFormat,0, N_("PTP Invalid Device Prop Format")}, + {PTP_RC_InvalidDevicePropValue, 0, N_("PTP Invalid Device Prop Value")}, + {PTP_RC_InvalidParameter, 0, N_("PTP Invalid Parameter")}, + {PTP_RC_SessionAlreadyOpened, 0, N_("PTP Session Already Opened")}, + {PTP_RC_TransactionCanceled, 0, N_("PTP Transaction Canceled")}, + {PTP_RC_SpecificationOfDestinationUnsupported, 0, N_("PTP Specification Of Destination Unsupported")}, + + {PTP_RC_EK_FilenameRequired, PTP_VENDOR_EASTMAN_KODAK, N_("Filename Required")}, + {PTP_RC_EK_FilenameConflicts, PTP_VENDOR_EASTMAN_KODAK, N_("Filename Conflicts")}, + {PTP_RC_EK_FilenameInvalid, PTP_VENDOR_EASTMAN_KODAK, N_("Filename Invalid")}, + + {PTP_RC_NIKON_HardwareError, PTP_VENDOR_NIKON, N_("Hardware Error")}, + {PTP_RC_NIKON_OutOfFocus, PTP_VENDOR_NIKON, N_("Out of Focus")}, + {PTP_RC_NIKON_ChangeCameraModeFailed, PTP_VENDOR_NIKON, N_("Change Camera Mode Failed")}, + {PTP_RC_NIKON_InvalidStatus, PTP_VENDOR_NIKON, N_("Invalid Status")}, + {PTP_RC_NIKON_SetPropertyNotSupported, PTP_VENDOR_NIKON, N_("Set Property Not Supported")}, + {PTP_RC_NIKON_WbResetError, PTP_VENDOR_NIKON, N_("Whitebalance Reset Error")}, + {PTP_RC_NIKON_DustReferenceError, PTP_VENDOR_NIKON, N_("Dust Reference Error")}, + {PTP_RC_NIKON_ShutterSpeedBulb, PTP_VENDOR_NIKON, N_("Shutter Speed Bulb")}, + {PTP_RC_NIKON_MirrorUpSequence, PTP_VENDOR_NIKON, N_("Mirror Up Sequence")}, + {PTP_RC_NIKON_CameraModeNotAdjustFNumber, PTP_VENDOR_NIKON, N_("Camera Mode Not Adjust FNumber")}, + {PTP_RC_NIKON_NotLiveView, PTP_VENDOR_NIKON, N_("Not in Liveview")}, + {PTP_RC_NIKON_MfDriveStepEnd, PTP_VENDOR_NIKON, N_("Mf Drive Step End")}, + {PTP_RC_NIKON_MfDriveStepInsufficiency, PTP_VENDOR_NIKON, N_("Mf Drive Step Insufficiency")}, + {PTP_RC_NIKON_AdvancedTransferCancel, PTP_VENDOR_NIKON, N_("Advanced Transfer Cancel")}, + + {PTP_RC_CANON_UNKNOWN_COMMAND, PTP_VENDOR_CANON, N_("Unknown Command")}, + {PTP_RC_CANON_OPERATION_REFUSED,PTP_VENDOR_CANON, N_("Operation Refused")}, + {PTP_RC_CANON_LENS_COVER, PTP_VENDOR_CANON, N_("Lens Cover Present")}, + {PTP_RC_CANON_BATTERY_LOW, PTP_VENDOR_CANON, N_("Battery Low")}, + {PTP_RC_CANON_NOT_READY, PTP_VENDOR_CANON, N_("Camera Not Ready")}, + + {PTP_ERROR_TIMEOUT, 0, N_("PTP Timeout")}, + {PTP_ERROR_CANCEL, 0, N_("PTP Cancel Request")}, + {PTP_ERROR_BADPARAM, 0, N_("PTP Invalid Parameter")}, + {PTP_ERROR_RESP_EXPECTED, 0, N_("PTP Response Expected")}, + {PTP_ERROR_DATA_EXPECTED, 0, N_("PTP Data Expected")}, + {PTP_ERROR_IO, 0, N_("PTP I/O Error")}, + {0, 0, NULL} +}; +const char * +ptp_strerror(uint16_t ret, uint16_t vendor) +{ int i; - /* PTP error descriptions */ - static struct { - short n; - const char *txt; - } ptp_errors[] = { - {PTP_RC_Undefined, N_("PTP: Undefined Error")}, - {PTP_RC_OK, N_("PTP: OK!")}, - {PTP_RC_GeneralError, N_("PTP: General Error")}, - {PTP_RC_SessionNotOpen, N_("PTP: Session Not Open")}, - {PTP_RC_InvalidTransactionID, N_("PTP: Invalid Transaction ID")}, - {PTP_RC_OperationNotSupported, N_("PTP: Operation Not Supported")}, - {PTP_RC_ParameterNotSupported, N_("PTP: Parameter Not Supported")}, - {PTP_RC_IncompleteTransfer, N_("PTP: Incomplete Transfer")}, - {PTP_RC_InvalidStorageId, N_("PTP: Invalid Storage ID")}, - {PTP_RC_InvalidObjectHandle, N_("PTP: Invalid Object Handle")}, - {PTP_RC_DevicePropNotSupported, N_("PTP: Device Prop Not Supported")}, - {PTP_RC_InvalidObjectFormatCode, N_("PTP: Invalid Object Format Code")}, - {PTP_RC_StoreFull, N_("PTP: Store Full")}, - {PTP_RC_ObjectWriteProtected, N_("PTP: Object Write Protected")}, - {PTP_RC_StoreReadOnly, N_("PTP: Store Read Only")}, - {PTP_RC_AccessDenied, N_("PTP: Access Denied")}, - {PTP_RC_NoThumbnailPresent, N_("PTP: No Thumbnail Present")}, - {PTP_RC_SelfTestFailed, N_("PTP: Self Test Failed")}, - {PTP_RC_PartialDeletion, N_("PTP: Partial Deletion")}, - {PTP_RC_StoreNotAvailable, N_("PTP: Store Not Available")}, - {PTP_RC_SpecificationByFormatUnsupported, - N_("PTP: Specification By Format Unsupported")}, - {PTP_RC_NoValidObjectInfo, N_("PTP: No Valid Object Info")}, - {PTP_RC_InvalidCodeFormat, N_("PTP: Invalid Code Format")}, - {PTP_RC_UnknownVendorCode, N_("PTP: Unknown Vendor Code")}, - {PTP_RC_CaptureAlreadyTerminated, - N_("PTP: Capture Already Terminated")}, - {PTP_RC_DeviceBusy, N_("PTP: Device Busy")}, - {PTP_RC_InvalidParentObject, N_("PTP: Invalid Parent Object")}, - {PTP_RC_InvalidDevicePropFormat, N_("PTP: Invalid Device Prop Format")}, - {PTP_RC_InvalidDevicePropValue, N_("PTP: Invalid Device Prop Value")}, - {PTP_RC_InvalidParameter, N_("PTP: Invalid Parameter")}, - {PTP_RC_SessionAlreadyOpened, N_("PTP: Session Already Opened")}, - {PTP_RC_TransactionCanceled, N_("PTP: Transaction Canceled")}, - {PTP_RC_SpecificationOfDestinationUnsupported, - N_("PTP: Specification Of Destination Unsupported")}, - {PTP_RC_EK_FilenameRequired, N_("PTP: EK Filename Required")}, - {PTP_RC_EK_FilenameConflicts, N_("PTP: EK Filename Conflicts")}, - {PTP_RC_EK_FilenameInvalid, N_("PTP: EK Filename Invalid")}, - - {PTP_ERROR_IO, N_("PTP: I/O error")}, - {PTP_ERROR_BADPARAM, N_("PTP: Error: bad parameter")}, - {PTP_ERROR_DATA_EXPECTED, N_("PTP: Protocol error, data expected")}, - {PTP_ERROR_RESP_EXPECTED, N_("PTP: Protocol error, response expected")}, - {0, NULL} -}; - for (i=0; ptp_errors[i].txt!=NULL; i++) - if (ptp_errors[i].n == error) + for (i=0; ptp_errors[i].txt != NULL; i++) + if ((ptp_errors[i].rc == ret) && ((ptp_errors[i].vendor == 0) || (ptp_errors[i].vendor == vendor))) return ptp_errors[i].txt; return NULL; } -void -ptp_perror(PTPParams* params, uint16_t error) { - const char *txt = ptp_strerror(error); - if (txt != NULL) - ptp_error(params, txt); -} - const char* ptp_get_property_description(PTPParams* params, uint16_t dpc) { @@ -4481,6 +4297,19 @@ ptp_get_property_description(PTPParams* {PTP_DPC_UploadURL, N_("Upload URL")}, {PTP_DPC_Artist, N_("Artist")}, {PTP_DPC_CopyrightInfo, N_("Copyright Info")}, + {PTP_DPC_SupportedStreams, N_("Supported Streams")}, + {PTP_DPC_EnabledStreams, N_("Enabled Streams")}, + {PTP_DPC_VideoFormat, N_("Video Format")}, + {PTP_DPC_VideoResolution, N_("Video Resolution")}, + {PTP_DPC_VideoQuality, N_("Video Quality")}, + {PTP_DPC_VideoFrameRate, N_("Video Framerate")}, + {PTP_DPC_VideoContrast, N_("Video Contrast")}, + {PTP_DPC_VideoBrightness, N_("Video Brightness")}, + {PTP_DPC_AudioFormat, N_("Audio Format")}, + {PTP_DPC_AudioBitrate, N_("Audio Bitrate")}, + {PTP_DPC_AudioSamplingRate, N_("Audio Samplingrate")}, + {PTP_DPC_AudioBitPerSample, N_("Audio Bits per sample")}, + {PTP_DPC_AudioVolume, N_("Audio Volume")}, {0,NULL} }; struct { @@ -4825,6 +4654,8 @@ ptp_get_property_description(PTPParams* N_("Movie Card Slot")}, {PTP_DPC_NIKON_ManualMovieSetting, /* 0xD0A6 */ N_("Manual Movie Setting")}, + {PTP_DPC_NIKON_MovQuality, /* 0xD0A7 */ + N_("Movie Quality")}, {PTP_DPC_NIKON_MonitorOffDelay, /* 0xD0B3 */ N_("Monitor Off Delay")}, {PTP_DPC_NIKON_Bracketing, /* 0xD0C0 */ @@ -5066,6 +4897,23 @@ ptp_get_property_description(PTPParams* N_("Active Pic Ctrl Item")}, {PTP_DPC_NIKON_ChangePicCtrlItem, /* 0xD201 */ N_("Change Pic Ctrl Item")}, + /* nikon 1 stuff */ + {PTP_DPC_NIKON_1_ISO, /* 0xf002 */ + N_("ISO")}, + {PTP_DPC_NIKON_1_ImageSize, /* 0xf00a */ + N_("Image Size")}, + {PTP_DPC_NIKON_1_LongExposureNoiseReduction, /* 0xF00D */ + N_("Long Exposure Noise Reduction")}, + {PTP_DPC_NIKON_1_MovQuality, /* 0xF01C */ + N_("Movie Quality")}, + {PTP_DPC_NIKON_1_HiISONoiseReduction, /* 0xF00E */ + N_("High ISO Noise Reduction")}, + {PTP_DPC_NIKON_1_WhiteBalance, /* 0xF00C */ + N_("White Balance")}, + {PTP_DPC_NIKON_1_ImageCompression, /* 0xF009 */ + N_("Image Compression")}, + {PTP_DPC_NIKON_1_ActiveDLighting, /* 0xF00F */ + N_("Active D-Lighting")}, {0,NULL} }; struct { @@ -5105,6 +4953,60 @@ ptp_get_property_description(PTPParams* {0,NULL} }; + struct { + uint16_t dpc; + const char *txt; + } ptp_device_properties_SONY[] = { + {PTP_DPC_SONY_DPCCompensation, ("DOC Compensation")}, /* 0xD200 */ + {PTP_DPC_SONY_DRangeOptimize, ("DRangeOptimize")}, /* 0xD201 */ + {PTP_DPC_SONY_ImageSize, N_("Image size")}, /* 0xD203 */ + {PTP_DPC_SONY_ShutterSpeed, N_("Shutter speed")}, /* 0xD20D */ + {PTP_DPC_SONY_ColorTemp, N_("Color temperature")}, /* 0xD20F */ + {PTP_DPC_SONY_CCFilter, ("CC Filter")}, /* 0xD210 */ + {PTP_DPC_SONY_AspectRatio, N_("Aspect Ratio")}, /* 0xD211 */ + {PTP_DPC_SONY_FocusFound, N_("Focus status")}, /* 0xD213 */ + {PTP_DPC_SONY_ObjectInMemory, N_("Objects in memory")}, /* 0xD215 */ + {PTP_DPC_SONY_ExposeIndex, N_("Expose Index")}, /* 0xD216 */ + {PTP_DPC_SONY_BatteryLevel, N_("Battery Level")}, /* 0xD218 */ + {PTP_DPC_SONY_PictureEffect, N_("Picture Effect")}, /* 0xD21B */ + {PTP_DPC_SONY_ABFilter, N_("AB Filter")}, /* 0xD21C */ + {PTP_DPC_SONY_ISO, N_("ISO")}, /* 0xD21E */ + {PTP_DPC_SONY_Movie, N_("Movie")}, /* 0xD2C8 */ + {PTP_DPC_SONY_StillImage, N_("Still Image")}, /* 0xD2C7 */ + {0,NULL} + }; + + struct { + uint16_t dpc; + const char *txt; + } ptp_device_properties_PARROT[] = { + {PTP_DPC_PARROT_PhotoSensorEnableMask, "PhotoSensorEnableMask"}, /* 0xD201 */ + {PTP_DPC_PARROT_PhotoSensorsKeepOn, "PhotoSensorsKeepOn"}, /* 0xD202 */ + {PTP_DPC_PARROT_MultispectralImageSize, "MultispectralImageSize"}, /* 0xD203 */ + {PTP_DPC_PARROT_MainBitDepth, "MainBitDepth"}, /* 0xD204 */ + {PTP_DPC_PARROT_MultispectralBitDepth, "MultispectralBitDepth"}, /* 0xD205 */ + {PTP_DPC_PARROT_HeatingEnable, "HeatingEnable"}, /* 0xD206 */ + {PTP_DPC_PARROT_WifiStatus, "WifiStatus"}, /* 0xD207 */ + {PTP_DPC_PARROT_WifiSSID, "WifiSSID"}, /* 0xD208 */ + {PTP_DPC_PARROT_WifiEncryptionType, "WifiEncryptionType"}, /* 0xD209 */ + {PTP_DPC_PARROT_WifiPassphrase, "WifiPassphrase"}, /* 0xD20A */ + {PTP_DPC_PARROT_WifiChannel, "WifiChannel"}, /* 0xD20B */ + {PTP_DPC_PARROT_Localization, "Localization"}, /* 0xD20C */ + {PTP_DPC_PARROT_WifiMode, "WifiMode"}, /* 0xD20D */ + {PTP_DPC_PARROT_AntiFlickeringFrequency, "AntiFlickeringFrequency"}, /* 0xD210 */ + {PTP_DPC_PARROT_DisplayOverlayMask, "DisplayOverlayMask"}, /* 0xD211 */ + {PTP_DPC_PARROT_GPSInterval, "GPSInterval"}, /* 0xD212 */ + {PTP_DPC_PARROT_MultisensorsExposureMeteringMode,"MultisensorsExposureMeteringMode"}, /* 0xD213 */ + {PTP_DPC_PARROT_MultisensorsExposureTime, "MultisensorsExposureTime"}, /* 0xD214 */ + {PTP_DPC_PARROT_MultisensorsExposureProgramMode,"MultisensorsExposureProgramMode"}, /* 0xD215 */ + {PTP_DPC_PARROT_MultisensorsExposureIndex, "MultisensorsExposureIndex"}, /* 0xD216 */ + {PTP_DPC_PARROT_MultisensorsIrradianceGain, "MultisensorsIrradianceGain"}, /* 0xD217 */ + {PTP_DPC_PARROT_MultisensorsIrradianceIntegrationTime,"MultisensorsIrradianceIntegrationTime"}, /* 0xD218 */ + {PTP_DPC_PARROT_OverlapRate, "OverlapRate"}, /* 0xD219 */ + {0,NULL} + }; + + for (i=0; ptp_device_properties[i].txt!=NULL; i++) if (ptp_device_properties[i].dpc==dpc) return (ptp_device_properties[i].txt); @@ -5135,6 +5037,16 @@ ptp_get_property_description(PTPParams* if (ptp_device_properties_FUJI[i].dpc==dpc) return (ptp_device_properties_FUJI[i].txt); + if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_SONY) + for (i=0; ptp_device_properties_SONY[i].txt!=NULL; i++) + if (ptp_device_properties_SONY[i].dpc==dpc) + return (ptp_device_properties_SONY[i].txt); + if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_PARROT) + for (i=0; ptp_device_properties_PARROT[i].txt!=NULL; i++) + if (ptp_device_properties_PARROT[i].dpc==dpc) + return (ptp_device_properties_PARROT[i].txt); + + return NULL; } @@ -5822,9 +5734,14 @@ ptp_render_property_value(PTPParams* par switch (dpc) { case PTP_DPC_MTP_SynchronizationPartner: case PTP_DPC_MTP_DeviceFriendlyName: - return snprintf(out, length, "%s", dpd->CurrentValue.str); + if (dpd->DataType == PTP_DTC_STR) + return snprintf(out, length, "%s", dpd->CurrentValue.str); + else + return snprintf(out, length, "invalid type, expected STR"); case PTP_DPC_MTP_SecureTime: case PTP_DPC_MTP_DeviceCertificate: { + if (dpd->DataType != PTP_DTC_AUINT16) + return snprintf(out, length, "invalid type, expected AUINT16"); /* FIXME: Convert to use unicode demux functions */ for (i=0;(i<dpd->CurrentValue.a.count) && (i<length);i++) out[i] = dpd->CurrentValue.a.v[i].u16; @@ -5971,6 +5888,14 @@ ptp_render_ofc(PTPParams* params, uint16 break; } break; + case PTP_VENDOR_SONY: + switch (ofc) { + case PTP_OFC_SONY_RAW: + return snprintf (txt, spaceleft,"ARW"); + default: + break; + } + break; case PTP_VENDOR_MICROSOFT: case PTP_VENDOR_MTP: for (i=0;i<sizeof(ptp_ofc_mtp_trans)/sizeof(ptp_ofc_mtp_trans[0]);i++) @@ -5983,12 +5908,14 @@ ptp_render_ofc(PTPParams* params, uint16 return snprintf (txt, spaceleft,_("Unknown(%04x)"), ofc); } -struct { +typedef struct { uint16_t opcode; const char *name; -} ptp_opcode_trans[] = { +} ptp_opcode_trans_t; + +ptp_opcode_trans_t ptp_opcode_trans[] = { {PTP_OC_Undefined,N_("Undefined")}, - {PTP_OC_GetDeviceInfo,N_("get device info")}, + {PTP_OC_GetDeviceInfo,N_("Get device info")}, {PTP_OC_OpenSession,N_("Open session")}, {PTP_OC_CloseSession,N_("Close session")}, {PTP_OC_GetStorageIDs,N_("Get storage IDs")}, @@ -6015,13 +5942,20 @@ struct { {PTP_OC_MoveObject,N_("Move object")}, {PTP_OC_CopyObject,N_("Copy object")}, {PTP_OC_GetPartialObject,N_("Get partial object")}, - {PTP_OC_InitiateOpenCapture,N_("Initiate open capture")} + {PTP_OC_InitiateOpenCapture,N_("Initiate open capture")}, + /* PTP v1.1 operation codes */ + {PTP_OC_StartEnumHandles,N_("Start Enumerate Handles")}, + {PTP_OC_EnumHandles,N_("Enumerate Handles")}, + {PTP_OC_StopEnumHandles,N_("Stop Enumerate Handles")}, + {PTP_OC_GetVendorExtensionMaps,N_("Get Vendor Extension Maps")}, + {PTP_OC_GetVendorDeviceInfo,N_("Get Vendor Device Info")}, + {PTP_OC_GetResizedImageObject,N_("Get Resized Image Object")}, + {PTP_OC_GetFilesystemManifest,N_("Get Filesystem Manifest")}, + {PTP_OC_GetStreamInfo,N_("Get Stream Info")}, + {PTP_OC_GetStream,N_("Get Stream")}, }; -struct { - uint16_t opcode; - const char *name; -} ptp_opcode_mtp_trans[] = { +ptp_opcode_trans_t ptp_opcode_mtp_trans[] = { {PTP_OC_MTP_GetObjectPropsSupported,N_("Get object properties supported")}, {PTP_OC_MTP_GetObjectPropDesc,N_("Get object property description")}, {PTP_OC_MTP_GetObjectPropValue,N_("Get object property value")}, @@ -6085,27 +6019,248 @@ struct { {PTP_OC_ANDROID_EndEditObject,N_("End Edit Object")}, }; -int -ptp_render_opcode(PTPParams* params, uint16_t opcode, int spaceleft, char *txt) -{ - unsigned int i; +ptp_opcode_trans_t ptp_opcode_nikon_trans[] = { + {PTP_OC_NIKON_GetProfileAllData,"PTP_OC_NIKON_GetProfileAllData"}, + {PTP_OC_NIKON_SendProfileData,"PTP_OC_NIKON_SendProfileData"}, + {PTP_OC_NIKON_DeleteProfile,"PTP_OC_NIKON_DeleteProfile"}, + {PTP_OC_NIKON_SetProfileData,"PTP_OC_NIKON_SetProfileData"}, + {PTP_OC_NIKON_AdvancedTransfer,"PTP_OC_NIKON_AdvancedTransfer"}, + {PTP_OC_NIKON_GetFileInfoInBlock,"PTP_OC_NIKON_GetFileInfoInBlock"}, + {PTP_OC_NIKON_Capture,"PTP_OC_NIKON_Capture"}, + {PTP_OC_NIKON_AfDrive,"PTP_OC_NIKON_AfDrive"}, + {PTP_OC_NIKON_SetControlMode,"PTP_OC_NIKON_SetControlMode"}, + {PTP_OC_NIKON_DelImageSDRAM,"PTP_OC_NIKON_DelImageSDRAM"}, + {PTP_OC_NIKON_GetLargeThumb,"PTP_OC_NIKON_GetLargeThumb"}, + {PTP_OC_NIKON_CurveDownload,"PTP_OC_NIKON_CurveDownload"}, + {PTP_OC_NIKON_CurveUpload,"PTP_OC_NIKON_CurveUpload"}, + {PTP_OC_NIKON_CheckEvent,"PTP_OC_NIKON_CheckEvent"}, + {PTP_OC_NIKON_DeviceReady,"PTP_OC_NIKON_DeviceReady"}, + {PTP_OC_NIKON_SetPreWBData,"PTP_OC_NIKON_SetPreWBData"}, + {PTP_OC_NIKON_GetVendorPropCodes,"PTP_OC_NIKON_GetVendorPropCodes"}, + {PTP_OC_NIKON_AfCaptureSDRAM,"PTP_OC_NIKON_AfCaptureSDRAM"}, + {PTP_OC_NIKON_GetPictCtrlData,"PTP_OC_NIKON_GetPictCtrlData"}, + {PTP_OC_NIKON_SetPictCtrlData,"PTP_OC_NIKON_SetPictCtrlData"}, + {PTP_OC_NIKON_DelCstPicCtrl,"PTP_OC_NIKON_DelCstPicCtrl"}, + {PTP_OC_NIKON_GetPicCtrlCapability,"PTP_OC_NIKON_GetPicCtrlCapability"}, + {PTP_OC_NIKON_GetPreviewImg,"PTP_OC_NIKON_GetPreviewImg"}, + {PTP_OC_NIKON_StartLiveView,"PTP_OC_NIKON_StartLiveView"}, + {PTP_OC_NIKON_EndLiveView,"PTP_OC_NIKON_EndLiveView"}, + {PTP_OC_NIKON_GetLiveViewImg,"PTP_OC_NIKON_GetLiveViewImg"}, + {PTP_OC_NIKON_MfDrive,"PTP_OC_NIKON_MfDrive"}, + {PTP_OC_NIKON_ChangeAfArea,"PTP_OC_NIKON_ChangeAfArea"}, + {PTP_OC_NIKON_AfDriveCancel,"PTP_OC_NIKON_AfDriveCancel"}, + {PTP_OC_NIKON_InitiateCaptureRecInMedia,"PTP_OC_NIKON_InitiateCaptureRecInMedia"}, + {PTP_OC_NIKON_GetVendorStorageIDs,"PTP_OC_NIKON_GetVendorStorageIDs"}, + {PTP_OC_NIKON_StartMovieRecInCard,"PTP_OC_NIKON_StartMovieRecInCard"}, + {PTP_OC_NIKON_EndMovieRec,"PTP_OC_NIKON_EndMovieRec"}, + {PTP_OC_NIKON_TerminateCapture,"PTP_OC_NIKON_TerminateCapture"}, + {PTP_OC_NIKON_GetDevicePTPIPInfo,"PTP_OC_NIKON_GetDevicePTPIPInfo"}, + {PTP_OC_NIKON_GetPartialObjectHiSpeed,"PTP_OC_NIKON_GetPartialObjectHiSpeed"}, + {PTP_OC_NIKON_GetDevicePropEx,"PTP_OC_NIKON_GetDevicePropEx"}, +}; - if (!(opcode & 0x8000)) { - for (i=0;i<sizeof(ptp_opcode_trans)/sizeof(ptp_opcode_trans[0]);i++) - if (opcode == ptp_opcode_trans[i].opcode) - return snprintf(txt, spaceleft, "%s", _(ptp_opcode_trans[i].name)); - } else { - switch (params->deviceinfo.VendorExtensionID) { - case PTP_VENDOR_MICROSOFT: - case PTP_VENDOR_MTP: - for (i=0;i<sizeof(ptp_opcode_mtp_trans)/sizeof(ptp_opcode_mtp_trans[0]);i++) - if (opcode == ptp_opcode_mtp_trans[i].opcode) - return snprintf(txt, spaceleft, "%s", _(ptp_opcode_mtp_trans[i].name)); - break; - default:break; - } +ptp_opcode_trans_t ptp_opcode_canon_trans[] = { + {PTP_OC_CANON_GetPartialObjectInfo,"PTP_OC_CANON_GetPartialObjectInfo"}, + {PTP_OC_CANON_SetObjectArchive,"PTP_OC_CANON_SetObjectArchive"}, + {PTP_OC_CANON_KeepDeviceOn,"PTP_OC_CANON_KeepDeviceOn"}, + {PTP_OC_CANON_LockDeviceUI,"PTP_OC_CANON_LockDeviceUI"}, + {PTP_OC_CANON_UnlockDeviceUI,"PTP_OC_CANON_UnlockDeviceUI"}, + {PTP_OC_CANON_GetObjectHandleByName,"PTP_OC_CANON_GetObjectHandleByName"}, + {PTP_OC_CANON_InitiateReleaseControl,"PTP_OC_CANON_InitiateReleaseControl"}, + {PTP_OC_CANON_TerminateReleaseControl,"PTP_OC_CANON_TerminateReleaseControl"}, + {PTP_OC_CANON_TerminatePlaybackMode,"PTP_OC_CANON_TerminatePlaybackMode"}, + {PTP_OC_CANON_ViewfinderOn,"PTP_OC_CANON_ViewfinderOn"}, + {PTP_OC_CANON_ViewfinderOff,"PTP_OC_CANON_ViewfinderOff"}, + {PTP_OC_CANON_DoAeAfAwb,"PTP_OC_CANON_DoAeAfAwb"}, + {PTP_OC_CANON_GetCustomizeSpec,"PTP_OC_CANON_GetCustomizeSpec"}, + {PTP_OC_CANON_GetCustomizeItemInfo,"PTP_OC_CANON_GetCustomizeItemInfo"}, + {PTP_OC_CANON_GetCustomizeData,"PTP_OC_CANON_GetCustomizeData"}, + {PTP_OC_CANON_SetCustomizeData,"PTP_OC_CANON_SetCustomizeData"}, + {PTP_OC_CANON_GetCaptureStatus,"PTP_OC_CANON_GetCaptureStatus"}, + {PTP_OC_CANON_CheckEvent,"PTP_OC_CANON_CheckEvent"}, + {PTP_OC_CANON_FocusLock,"PTP_OC_CANON_FocusLock"}, + {PTP_OC_CANON_FocusUnlock,"PTP_OC_CANON_FocusUnlock"}, + {PTP_OC_CANON_GetLocalReleaseParam,"PTP_OC_CANON_GetLocalReleaseParam"}, + {PTP_OC_CANON_SetLocalReleaseParam,"PTP_OC_CANON_SetLocalReleaseParam"}, + {PTP_OC_CANON_AskAboutPcEvf,"PTP_OC_CANON_AskAboutPcEvf"}, + {PTP_OC_CANON_SendPartialObject,"PTP_OC_CANON_SendPartialObject"}, + {PTP_OC_CANON_InitiateCaptureInMemory,"PTP_OC_CANON_InitiateCaptureInMemory"}, + {PTP_OC_CANON_GetPartialObjectEx,"PTP_OC_CANON_GetPartialObjectEx"}, + {PTP_OC_CANON_SetObjectTime,"PTP_OC_CANON_SetObjectTime"}, + {PTP_OC_CANON_GetViewfinderImage,"PTP_OC_CANON_GetViewfinderImage"}, + {PTP_OC_CANON_GetObjectAttributes,"PTP_OC_CANON_GetObjectAttributes"}, + {PTP_OC_CANON_ChangeUSBProtocol,"PTP_OC_CANON_ChangeUSBProtocol"}, + {PTP_OC_CANON_GetChanges,"PTP_OC_CANON_GetChanges"}, + {PTP_OC_CANON_GetObjectInfoEx,"PTP_OC_CANON_GetObjectInfoEx"}, + {PTP_OC_CANON_InitiateDirectTransfer,"PTP_OC_CANON_InitiateDirectTransfer"}, + {PTP_OC_CANON_TerminateDirectTransfer ,"PTP_OC_CANON_TerminateDirectTransfer "}, + {PTP_OC_CANON_SendObjectInfoByPath ,"PTP_OC_CANON_SendObjectInfoByPath "}, + {PTP_OC_CANON_SendObjectByPath ,"PTP_OC_CANON_SendObjectByPath "}, + {PTP_OC_CANON_InitiateDirectTansferEx,"PTP_OC_CANON_InitiateDirectTansferEx"}, + {PTP_OC_CANON_GetAncillaryObjectHandles,"PTP_OC_CANON_GetAncillaryObjectHandles"}, + {PTP_OC_CANON_GetTreeInfo ,"PTP_OC_CANON_GetTreeInfo "}, + {PTP_OC_CANON_GetTreeSize ,"PTP_OC_CANON_GetTreeSize "}, + {PTP_OC_CANON_NotifyProgress ,"PTP_OC_CANON_NotifyProgress "}, + {PTP_OC_CANON_NotifyCancelAccepted,"PTP_OC_CANON_NotifyCancelAccepted"}, + {PTP_OC_CANON_902C,"PTP_OC_CANON_902C"}, + {PTP_OC_CANON_GetDirectory,"PTP_OC_CANON_GetDirectory"}, + {PTP_OC_CANON_SetPairingInfo,"PTP_OC_CANON_SetPairingInfo"}, + {PTP_OC_CANON_GetPairingInfo,"PTP_OC_CANON_GetPairingInfo"}, + {PTP_OC_CANON_DeletePairingInfo,"PTP_OC_CANON_DeletePairingInfo"}, + {PTP_OC_CANON_GetMACAddress,"PTP_OC_CANON_GetMACAddress"}, + {PTP_OC_CANON_SetDisplayMonitor,"PTP_OC_CANON_SetDisplayMonitor"}, + {PTP_OC_CANON_PairingComplete,"PTP_OC_CANON_PairingComplete"}, + {PTP_OC_CANON_GetWirelessMAXChannel,"PTP_OC_CANON_GetWirelessMAXChannel"}, + {PTP_OC_CANON_GetWebServiceSpec,"PTP_OC_CANON_GetWebServiceSpec"}, + {PTP_OC_CANON_GetWebServiceData,"PTP_OC_CANON_GetWebServiceData"}, + {PTP_OC_CANON_SetWebServiceData,"PTP_OC_CANON_SetWebServiceData"}, + {PTP_OC_CANON_GetRootCertificateSpec,"PTP_OC_CANON_GetRootCertificateSpec"}, + {PTP_OC_CANON_GetRootCertificateData,"PTP_OC_CANON_GetRootCertificateData"}, + {PTP_OC_CANON_SetRootCertificateData,"PTP_OC_CANON_SetRootCertificateData"}, + {PTP_OC_CANON_EOS_GetStorageIDs,"PTP_OC_CANON_EOS_GetStorageIDs"}, + {PTP_OC_CANON_EOS_GetStorageInfo,"PTP_OC_CANON_EOS_GetStorageInfo"}, + {PTP_OC_CANON_EOS_GetObjectInfo,"PTP_OC_CANON_EOS_GetObjectInfo"}, + {PTP_OC_CANON_EOS_GetObject,"PTP_OC_CANON_EOS_GetObject"}, + {PTP_OC_CANON_EOS_DeleteObject,"PTP_OC_CANON_EOS_DeleteObject"}, + {PTP_OC_CANON_EOS_FormatStore,"PTP_OC_CANON_EOS_FormatStore"}, + {PTP_OC_CANON_EOS_GetPartialObject,"PTP_OC_CANON_EOS_GetPartialObject"}, + {PTP_OC_CANON_EOS_GetDeviceInfoEx,"PTP_OC_CANON_EOS_GetDeviceInfoEx"}, + {PTP_OC_CANON_EOS_GetObjectInfoEx,"PTP_OC_CANON_EOS_GetObjectInfoEx"}, + {PTP_OC_CANON_EOS_GetThumbEx,"PTP_OC_CANON_EOS_GetThumbEx"}, + {PTP_OC_CANON_EOS_SendPartialObject,"PTP_OC_CANON_EOS_SendPartialObject"}, + {PTP_OC_CANON_EOS_SetObjectAttributes,"PTP_OC_CANON_EOS_SetObjectAttributes"}, + {PTP_OC_CANON_EOS_GetObjectTime,"PTP_OC_CANON_EOS_GetObjectTime"}, + {PTP_OC_CANON_EOS_SetObjectTime,"PTP_OC_CANON_EOS_SetObjectTime"}, + {PTP_OC_CANON_EOS_RemoteRelease,"PTP_OC_CANON_EOS_RemoteRelease"}, + {PTP_OC_CANON_EOS_SetDevicePropValueEx,"PTP_OC_CANON_EOS_SetDevicePropValueEx"}, + {PTP_OC_CANON_EOS_GetRemoteMode,"PTP_OC_CANON_EOS_GetRemoteMode"}, + {PTP_OC_CANON_EOS_SetRemoteMode,"PTP_OC_CANON_EOS_SetRemoteMode"}, + {PTP_OC_CANON_EOS_SetEventMode,"PTP_OC_CANON_EOS_SetEventMode"}, + {PTP_OC_CANON_EOS_GetEvent,"PTP_OC_CANON_EOS_GetEvent"}, + {PTP_OC_CANON_EOS_TransferComplete,"PTP_OC_CANON_EOS_TransferComplete"}, + {PTP_OC_CANON_EOS_CancelTransfer,"PTP_OC_CANON_EOS_CancelTransfer"}, + {PTP_OC_CANON_EOS_ResetTransfer,"PTP_OC_CANON_EOS_ResetTransfer"}, + {PTP_OC_CANON_EOS_PCHDDCapacity,"PTP_OC_CANON_EOS_PCHDDCapacity"}, + {PTP_OC_CANON_EOS_SetUILock,"PTP_OC_CANON_EOS_SetUILock"}, + {PTP_OC_CANON_EOS_ResetUILock,"PTP_OC_CANON_EOS_ResetUILock"}, + {PTP_OC_CANON_EOS_KeepDeviceOn,"PTP_OC_CANON_EOS_KeepDeviceOn"}, + {PTP_OC_CANON_EOS_SetNullPacketMode,"PTP_OC_CANON_EOS_SetNullPacketMode"}, + {PTP_OC_CANON_EOS_UpdateFirmware,"PTP_OC_CANON_EOS_UpdateFirmware"}, + {PTP_OC_CANON_EOS_TransferCompleteDT,"PTP_OC_CANON_EOS_TransferCompleteDT"}, + {PTP_OC_CANON_EOS_CancelTransferDT,"PTP_OC_CANON_EOS_CancelTransferDT"}, + {PTP_OC_CANON_EOS_SetWftProfile,"PTP_OC_CANON_EOS_SetWftProfile"}, + {PTP_OC_CANON_EOS_GetWftProfile,"PTP_OC_CANON_EOS_GetWftProfile"}, + {PTP_OC_CANON_EOS_SetProfileToWft,"PTP_OC_CANON_EOS_SetProfileToWft"}, + {PTP_OC_CANON_EOS_BulbStart,"PTP_OC_CANON_EOS_BulbStart"}, + {PTP_OC_CANON_EOS_BulbEnd,"PTP_OC_CANON_EOS_BulbEnd"}, + {PTP_OC_CANON_EOS_RequestDevicePropValue,"PTP_OC_CANON_EOS_RequestDevicePropValue"}, + {PTP_OC_CANON_EOS_RemoteReleaseOn,"PTP_OC_CANON_EOS_RemoteReleaseOn"}, + {PTP_OC_CANON_EOS_RemoteReleaseOff,"PTP_OC_CANON_EOS_RemoteReleaseOff"}, + {PTP_OC_CANON_EOS_RegistBackgroundImage,"PTP_OC_CANON_EOS_RegistBackgroundImage"}, + {PTP_OC_CANON_EOS_ChangePhotoStudioMode,"PTP_OC_CANON_EOS_ChangePhotoStudioMode"}, + {PTP_OC_CANON_EOS_GetPartialObjectEx,"PTP_OC_CANON_EOS_GetPartialObjectEx"}, + {PTP_OC_CANON_EOS_ResetMirrorLockupState,"PTP_OC_CANON_EOS_ResetMirrorLockupState"}, + {PTP_OC_CANON_EOS_PopupBuiltinFlash,"PTP_OC_CANON_EOS_PopupBuiltinFlash"}, + {PTP_OC_CANON_EOS_EndGetPartialObjectEx,"PTP_OC_CANON_EOS_EndGetPartialObjectEx"}, + {PTP_OC_CANON_EOS_MovieSelectSWOn,"PTP_OC_CANON_EOS_MovieSelectSWOn"}, + {PTP_OC_CANON_EOS_MovieSelectSWOff,"PTP_OC_CANON_EOS_MovieSelectSWOff"}, + {PTP_OC_CANON_EOS_GetCTGInfo,"PTP_OC_CANON_EOS_GetCTGInfo"}, + {PTP_OC_CANON_EOS_GetLensAdjust,"PTP_OC_CANON_EOS_GetLensAdjust"}, + {PTP_OC_CANON_EOS_SetLensAdjust,"PTP_OC_CANON_EOS_SetLensAdjust"}, + {PTP_OC_CANON_EOS_GetMusicInfo,"PTP_OC_CANON_EOS_GetMusicInfo"}, + {PTP_OC_CANON_EOS_CreateHandle,"PTP_OC_CANON_EOS_CreateHandle"}, + {PTP_OC_CANON_EOS_SendPartialObjectEx,"PTP_OC_CANON_EOS_SendPartialObjectEx"}, + {PTP_OC_CANON_EOS_EndSendPartialObjectEx,"PTP_OC_CANON_EOS_EndSendPartialObjectEx"}, + {PTP_OC_CANON_EOS_SetCTGInfo,"PTP_OC_CANON_EOS_SetCTGInfo"}, + {PTP_OC_CANON_EOS_SetRequestOLCInfoGroup,"PTP_OC_CANON_EOS_SetRequestOLCInfoGroup"}, + {PTP_OC_CANON_EOS_SetRequestRollingPitchingLevel,"PTP_OC_CANON_EOS_SetRequestRollingPitchingLevel"}, + {PTP_OC_CANON_EOS_GetCameraSupport,"PTP_OC_CANON_EOS_GetCameraSupport"}, + {PTP_OC_CANON_EOS_SetRating,"PTP_OC_CANON_EOS_SetRating"}, + {PTP_OC_CANON_EOS_RequestInnerDevelopStart,"PTP_OC_CANON_EOS_RequestInnerDevelopStart"}, + {PTP_OC_CANON_EOS_RequestInnerDevelopParamChange,"PTP_OC_CANON_EOS_RequestInnerDevelopParamChange"}, + {PTP_OC_CANON_EOS_RequestInnerDevelopEnd,"PTP_OC_CANON_EOS_RequestInnerDevelopEnd"}, + {PTP_OC_CANON_EOS_GpsLoggingDataMode,"PTP_OC_CANON_EOS_GpsLoggingDataMode"}, + {PTP_OC_CANON_EOS_GetGpsLogCurrentHandle,"PTP_OC_CANON_EOS_GetGpsLogCurrentHandle"}, + {PTP_OC_CANON_EOS_InitiateViewfinder,"PTP_OC_CANON_EOS_InitiateViewfinder"}, + {PTP_OC_CANON_EOS_TerminateViewfinder,"PTP_OC_CANON_EOS_TerminateViewfinder"}, + {PTP_OC_CANON_EOS_GetViewFinderData,"PTP_OC_CANON_EOS_GetViewFinderData"}, + {PTP_OC_CANON_EOS_DoAf,"PTP_OC_CANON_EOS_DoAf"}, + {PTP_OC_CANON_EOS_DriveLens,"PTP_OC_CANON_EOS_DriveLens"}, + {PTP_OC_CANON_EOS_DepthOfFieldPreview,"PTP_OC_CANON_EOS_DepthOfFieldPreview"}, + {PTP_OC_CANON_EOS_ClickWB,"PTP_OC_CANON_EOS_ClickWB"}, + {PTP_OC_CANON_EOS_Zoom,"PTP_OC_CANON_EOS_Zoom"}, + {PTP_OC_CANON_EOS_ZoomPosition,"PTP_OC_CANON_EOS_ZoomPosition"}, + {PTP_OC_CANON_EOS_SetLiveAfFrame,"PTP_OC_CANON_EOS_SetLiveAfFrame"}, + {PTP_OC_CANON_EOS_TouchAfPosition,"PTP_OC_CANON_EOS_TouchAfPosition"}, + {PTP_OC_CANON_EOS_SetLvPcFlavoreditMode,"PTP_OC_CANON_EOS_SetLvPcFlavoreditMode"}, + {PTP_OC_CANON_EOS_SetLvPcFlavoreditParam,"PTP_OC_CANON_EOS_SetLvPcFlavoreditParam"}, + {PTP_OC_CANON_EOS_AfCancel,"PTP_OC_CANON_EOS_AfCancel"}, + {PTP_OC_CANON_EOS_SetDefaultCameraSetting,"PTP_OC_CANON_EOS_SetDefaultCameraSetting"}, + {PTP_OC_CANON_EOS_GetAEData,"PTP_OC_CANON_EOS_GetAEData"}, + {PTP_OC_CANON_EOS_NotifyNetworkError,"PTP_OC_CANON_EOS_NotifyNetworkError"}, + {PTP_OC_CANON_EOS_AdapterTransferProgress,"PTP_OC_CANON_EOS_AdapterTransferProgress"}, + {PTP_OC_CANON_EOS_TransferComplete2,"PTP_OC_CANON_EOS_TransferComplete2"}, + {PTP_OC_CANON_EOS_CancelTransfer2,"PTP_OC_CANON_EOS_CancelTransfer2"}, + {PTP_OC_CANON_EOS_FAPIMessageTX,"PTP_OC_CANON_EOS_FAPIMessageTX"}, + {PTP_OC_CANON_EOS_FAPIMessageRX,"PTP_OC_CANON_EOS_FAPIMessageRX"}, +}; + +ptp_opcode_trans_t ptp_opcode_sony_trans[] = { + {PTP_OC_SONY_SDIOConnect,"PTP_OC_SONY_SDIOConnect"}, + {PTP_OC_SONY_GetSDIOGetExtDeviceInfo,"PTP_OC_SONY_GetSDIOGetExtDeviceInfo"}, + {PTP_OC_SONY_GetDevicePropdesc,"PTP_OC_SONY_GetDevicePropdesc"}, + {PTP_OC_SONY_GetDevicePropertyValue,"PTP_OC_SONY_GetDevicePropertyValue"}, + {PTP_OC_SONY_SetControlDeviceA,"PTP_OC_SONY_SetControlDeviceA"}, + {PTP_OC_SONY_GetControlDeviceDesc,"PTP_OC_SONY_GetControlDeviceDesc"}, + {PTP_OC_SONY_SetControlDeviceB,"PTP_OC_SONY_SetControlDeviceB"}, + {PTP_OC_SONY_GetAllDevicePropData,"PTP_OC_SONY_GetAllDevicePropData"}, +}; + +ptp_opcode_trans_t ptp_opcode_parrot_trans[] = { + {PTP_OC_PARROT_GetSunshineValues,"PTP_OC_PARROT_GetSunshineValues"}, + {PTP_OC_PARROT_GetTemperatureValues,"PTP_OC_PARROT_GetTemperatureValues"}, + {PTP_OC_PARROT_GetAngleValues,"PTP_OC_PARROT_GetAngleValues"}, + {PTP_OC_PARROT_GetGpsValues,"PTP_OC_PARROT_GetGpsValues"}, + {PTP_OC_PARROT_GetGyroscopeValues,"PTP_OC_PARROT_GetGyroscopeValues"}, + {PTP_OC_PARROT_GetAccelerometerValues,"PTP_OC_PARROT_GetAccelerometerValues"}, + {PTP_OC_PARROT_GetMagnetometerValues,"PTP_OC_PARROT_GetMagnetometerValues"}, + {PTP_OC_PARROT_GetImuValues,"PTP_OC_PARROT_GetImuValues"}, + {PTP_OC_PARROT_GetStatusMask,"PTP_OC_PARROT_GetStatusMask"}, + {PTP_OC_PARROT_EjectStorage,"PTP_OC_PARROT_EjectStorage"}, + {PTP_OC_PARROT_StartMagnetoCalib,"PTP_OC_PARROT_StartMagnetoCalib"}, + {PTP_OC_PARROT_StopMagnetoCalib,"PTP_OC_PARROT_StopMagnetoCalib"}, + {PTP_OC_PARROT_MagnetoCalibStatus,"PTP_OC_PARROT_MagnetoCalibStatus"}, + {PTP_OC_PARROT_SendFirmwareUpdate,"PTP_OC_PARROT_SendFirmwareUpdate"}, +}; + +const char* +ptp_get_opcode_name(PTPParams* params, uint16_t opcode) +{ +#define RETURN_NAME_FROM_TABLE(TABLE, OPCODE) \ +{ \ + unsigned int i; \ + for (i=0; i<sizeof(TABLE)/sizeof(TABLE[0]); i++) \ + if (OPCODE == TABLE[i].opcode) \ + return _(TABLE[i].name); \ + return _("Unknown PTP_OC"); \ +} + + if (!(opcode & 0x8000)) + RETURN_NAME_FROM_TABLE(ptp_opcode_trans, opcode); + + switch (params->deviceinfo.VendorExtensionID) { + case PTP_VENDOR_MICROSOFT: + case PTP_VENDOR_MTP: RETURN_NAME_FROM_TABLE(ptp_opcode_mtp_trans, opcode); + case PTP_VENDOR_NIKON: RETURN_NAME_FROM_TABLE(ptp_opcode_nikon_trans, opcode); + case PTP_VENDOR_CANON: RETURN_NAME_FROM_TABLE(ptp_opcode_canon_trans, opcode); + case PTP_VENDOR_SONY: RETURN_NAME_FROM_TABLE(ptp_opcode_sony_trans, opcode); + case PTP_VENDOR_PARROT: RETURN_NAME_FROM_TABLE(ptp_opcode_parrot_trans, opcode); + default: + break; } - return snprintf (txt, spaceleft,_("Unknown (%04x)"), opcode); +#undef RETURN_NAME_FROM_TABLE + + return _("Unknown VendorExtensionID"); } @@ -6284,7 +6439,8 @@ struct { }; int -ptp_render_mtp_propname(uint16_t propid, int spaceleft, char *txt) { +ptp_render_mtp_propname(uint16_t propid, int spaceleft, char *txt) +{ unsigned int i; for (i=0;i<sizeof(ptp_opc_trans)/sizeof(ptp_opc_trans[0]);i++) if (propid == ptp_opc_trans[i].id) @@ -6296,15 +6452,12 @@ ptp_render_mtp_propname(uint16_t propid, * Allocate and default-initialize a few object properties. */ MTPProperties * -ptp_get_new_object_prop_entry(MTPProperties **props, int *nrofprops) { +ptp_get_new_object_prop_entry(MTPProperties **props, int *nrofprops) +{ MTPProperties *newprops; MTPProperties *prop; - if (*props == NULL) { - newprops = malloc(sizeof(MTPProperties)*(*nrofprops+1)); - } else { - newprops = realloc(*props,sizeof(MTPProperties)*(*nrofprops+1)); - } + newprops = realloc(*props,sizeof(MTPProperties)*(*nrofprops+1)); if (newprops == NULL) return NULL; prop = &newprops[*nrofprops]; @@ -6369,16 +6522,13 @@ ptp_find_object_prop_in_cache(PTPParams return NULL; } -void +uint16_t ptp_remove_object_from_cache(PTPParams *params, uint32_t handle) { unsigned int i; PTPObject *ob; - uint16_t ret; - ret = ptp_object_find (params, handle, &ob); - if (ret != PTP_RC_OK) - return; + CHECK_PTP_RC(ptp_object_find (params, handle, &ob)); i = ob-params->objects; /* remove object from object info cache */ ptp_free_object (ob); @@ -6388,23 +6538,32 @@ ptp_remove_object_from_cache(PTPParams * params->nrofobjects--; /* We use less memory than before so this shouldn't fail */ params->objects = realloc(params->objects, sizeof(PTPObject)*params->nrofobjects); + return PTP_RC_OK; } -static int _cmp_ob (const void *a, const void *b) { +static int _cmp_ob (const void *a, const void *b) +{ PTPObject *oa = (PTPObject*)a; PTPObject *ob = (PTPObject*)b; - return oa->oid - ob->oid; + /* Do not subtract the oids and return ... + * the unsigned int -> int conversion will overflow in cases + * like 0xfffc0000 vs 0x0004000. */ + if (oa->oid > ob->oid) return 1; + if (oa->oid < ob->oid) return -1; + return 0; } void -ptp_objects_sort (PTPParams *params) { +ptp_objects_sort (PTPParams *params) +{ qsort (params->objects, params->nrofobjects, sizeof(PTPObject), _cmp_ob); } /* Binary search in objects. Needs "objects" to be a sorted by objectid list! */ uint16_t -ptp_object_find (PTPParams *params, uint32_t handle, PTPObject **retob) { +ptp_object_find (PTPParams *params, uint32_t handle, PTPObject **retob) +{ PTPObject tmpob; tmpob.oid = handle; @@ -6416,7 +6575,8 @@ ptp_object_find (PTPParams *params, uint /* Binary search in objects + insert of not found. Needs "objects" to be a sorted by objectid list! */ uint16_t -ptp_object_find_or_insert (PTPParams *params, uint32_t handle, PTPObject **retob) { +ptp_object_find_or_insert (PTPParams *params, uint32_t handle, PTPObject **retob) +{ unsigned int begin, end, cursor; unsigned int insertat; PTPObject *newobs; @@ -6477,7 +6637,8 @@ ptp_object_find_or_insert (PTPParams *pa } uint16_t -ptp_object_want (PTPParams *params, uint32_t handle, unsigned int want, PTPObject **retob) { +ptp_object_want (PTPParams *params, uint32_t handle, unsigned int want, PTPObject **retob) +{ uint16_t ret; PTPObject *ob; /*Camera *camera = ((PTPData *)params->data)->camera;*/ @@ -6491,9 +6652,7 @@ ptp_object_want (PTPParams *params, uint ptp_debug (params, "ptp_object_want: querying handle 0?\n"); return PTP_RC_GeneralError; } - ret = ptp_object_find_or_insert (params, handle, &ob); - if (ret != PTP_RC_OK) - return PTP_RC_GeneralError; + CHECK_PTP_RC(ptp_object_find_or_insert (params, handle, &ob)); *retob = ob; /* Do we have all of it already? */ if ((ob->flags & want) == want) --- libmtp-1.1.8/src/ptp.h.orig 2014-06-02 15:44:03.000000000 -0400 +++ libmtp-1.1.8/src/ptp.h 2017-07-08 14:39:24.512852305 -0400 @@ -1,7 +1,7 @@ /* ptp.h * * Copyright (C) 2001 Mariusz Woloszyn <emsi@ipartners.pl> - * Copyright (C) 2003-2012 Marcus Meissner <marcus@jet.franken.de> + * Copyright (C) 2003-2014 Marcus Meissner <marcus@jet.franken.de> * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se> * * This library is free software; you can redistribute it and/or @@ -25,7 +25,7 @@ #include <stdarg.h> #include <time.h> -#ifdef HAVE_ICONV +#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H) #include <iconv.h> #endif #include "gphoto2-endian.h" @@ -172,9 +172,13 @@ typedef struct _PTPIPHeader PTPIPHeader; /* not from standards papers, but from traces: */ #define PTP_VENDOR_SONY 0x00000011 /* observed in the A900 */ #define PTP_VENDOR_SAMSUNG 0x0000001a /* observed in the Samsung NX1000 */ +#define PTP_VENDOR_PARROT 0x0000001b /* observed in the Parrot Sequoia */ /* Vendor extension ID used for MTP (occasionaly, usualy 6 is used) */ #define PTP_VENDOR_MTP 0xffffffff +/* gphoto overrides */ +#define PTP_VENDOR_GP_OLYMPUS 0xfffffffe + /* Operation Codes */ /* PTP v1.0 operation codes */ @@ -275,6 +279,8 @@ typedef struct _PTPIPHeader PTPIPHeader; /* 902c: no parms, read 3 uint32 in data, no response parms */ #define PTP_OC_CANON_902C 0x902C #define PTP_OC_CANON_GetDirectory 0x902D +#define PTP_OC_CANON_902E 0x902E +#define PTP_OC_CANON_902F 0x902F /* used during camera init */ #define PTP_OC_CANON_SetPairingInfo 0x9030 #define PTP_OC_CANON_GetPairingInfo 0x9031 @@ -396,12 +402,14 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_OC_CANON_EOS_GetLensAdjust 0x9136 #define PTP_OC_CANON_EOS_SetLensAdjust 0x9137 #define PTP_OC_CANON_EOS_GetMusicInfo 0x9138 +/* 3 paramaeters, no data, OFC, size, unknown */ #define PTP_OC_CANON_EOS_CreateHandle 0x9139 #define PTP_OC_CANON_EOS_SendPartialObjectEx 0x913A #define PTP_OC_CANON_EOS_EndSendPartialObjectEx 0x913B #define PTP_OC_CANON_EOS_SetCTGInfo 0x913C #define PTP_OC_CANON_EOS_SetRequestOLCInfoGroup 0x913D #define PTP_OC_CANON_EOS_SetRequestRollingPitchingLevel 0x913E +/* 3 args, 0x21201020, 0x110, 0x1000000 (potentially reverse order) */ #define PTP_OC_CANON_EOS_GetCameraSupport 0x913F #define PTP_OC_CANON_EOS_SetRating 0x9140 /* 2 args */ #define PTP_OC_CANON_EOS_RequestInnerDevelopStart 0x9141 /* 2 args: 1 type, 1 object? */ @@ -412,6 +420,7 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_OC_CANON_EOS_InitiateViewfinder 0x9151 #define PTP_OC_CANON_EOS_TerminateViewfinder 0x9152 +/* EOS M2 wlan: 2 params, 0x00200000 0x01000000 */ #define PTP_OC_CANON_EOS_GetViewFinderData 0x9153 #define PTP_OC_CANON_EOS_DoAf 0x9154 #define PTP_OC_CANON_EOS_DriveLens 0x9155 @@ -433,6 +442,8 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_OC_CANON_EOS_FAPIMessageTX 0x91FE #define PTP_OC_CANON_EOS_FAPIMessageRX 0x91FF +/* A1E8 ... also seen? is an error code? */ + /* Nikon extension Operation Codes */ #define PTP_OC_NIKON_GetProfileAllData 0x9006 #define PTP_OC_NIKON_SendProfileData 0x9007 @@ -645,6 +656,40 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_OC_ANDROID_BeginEditObject 0x95C4 #define PTP_OC_ANDROID_EndEditObject 0x95C5 +/* Leica opcodes, from Lightroom tether plugin */ +#define PTP_OC_LEICA_SetCameraSettings 0x9001 +#define PTP_OC_LEICA_GetCameraSettings 0x9002 +#define PTP_OC_LEICA_GetLensParameter 0x9003 +/* probably 2 arguments. + * generic: releaseStage, stepSize + * Release(releasestage) = (releasestage,0) + * Release() = (0,0) + * AEStart() = (1,0) + * Autofocusrelease() = (2,0) + * AutofocusPush() = (1,0) ... same as AEStart? + * KeepCameraActive() = (0xe,0) + */ +#define PTP_OC_LEICA_Release 0x9004 +#define PTP_OC_LEICA_OpenLESession 0x9005 +#define PTP_OC_LEICA_CloseLESession 0x9006 +#define PTP_OC_LEICA_RequestObjectTransferReady 0x9007 + +#define PTP_OC_PARROT_GetSunshineValues 0x9201 +#define PTP_OC_PARROT_GetTemperatureValues 0x9202 +#define PTP_OC_PARROT_GetAngleValues 0x9203 +#define PTP_OC_PARROT_GetGpsValues 0x9204 +#define PTP_OC_PARROT_GetGyroscopeValues 0x9205 +#define PTP_OC_PARROT_GetAccelerometerValues 0x9206 +#define PTP_OC_PARROT_GetMagnetometerValues 0x9207 +#define PTP_OC_PARROT_GetImuValues 0x9208 +#define PTP_OC_PARROT_GetStatusMask 0x9209 +#define PTP_OC_PARROT_EjectStorage 0x920A +#define PTP_OC_PARROT_StartMagnetoCalib 0x9210 +#define PTP_OC_PARROT_StopMagnetoCalib 0x9211 +#define PTP_OC_PARROT_MagnetoCalibStatus 0x9212 +#define PTP_OC_PARROT_SendFirmwareUpdate 0x9213 + + /* Proprietary vendor extension operations mask */ #define PTP_OC_EXTENSION_MASK 0xF000 #define PTP_OC_EXTENSION 0x9000 @@ -720,6 +765,15 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_RC_CANON_A009 0xA009 +#define PTP_RC_CANON_EOS_UnknownCommand 0xA001 +#define PTP_RC_CANON_EOS_OperationRefused 0xA005 +#define PTP_RC_CANON_EOS_LensCoverClosed 0xA006 +#define PTP_RC_CANON_EOS_LowBattery 0xA101 +#define PTP_RC_CANON_EOS_ObjectNotReady 0xA102 +#define PTP_RC_CANON_EOS_CannotMakeObject 0xA104 +#define PTP_RC_CANON_EOS_MemoryStatusNotReady 0xA106 + + /* Microsoft/MTP specific codes */ #define PTP_RC_MTP_Undefined 0xA800 #define PTP_RC_MTP_Invalid_ObjectPropCode 0xA801 @@ -743,12 +797,12 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_RC_MTP_WFC_Version_Not_Supported 0xA122 /* libptp2 extended ERROR codes */ -#define PTP_ERROR_IO 0x02FF -#define PTP_ERROR_DATA_EXPECTED 0x02FE -#define PTP_ERROR_RESP_EXPECTED 0x02FD -#define PTP_ERROR_BADPARAM 0x02FC -#define PTP_ERROR_CANCEL 0x02FB #define PTP_ERROR_TIMEOUT 0x02FA +#define PTP_ERROR_CANCEL 0x02FB +#define PTP_ERROR_BADPARAM 0x02FC +#define PTP_ERROR_RESP_EXPECTED 0x02FD +#define PTP_ERROR_DATA_EXPECTED 0x02FE +#define PTP_ERROR_IO 0x02FF /* PTP Event Codes */ @@ -801,10 +855,12 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_EC_CANON_EOS_StoreRemoved 0xc193 #define PTP_EC_CANON_EOS_BulbExposureTime 0xc194 #define PTP_EC_CANON_EOS_RecordingTime 0xc195 -#define PTP_EC_CANON_EOS_RequestObjectTransferTS 0xC1a2 +#define PTP_EC_CANON_EOS_RequestObjectTransferTS 0xc1a2 #define PTP_EC_CANON_EOS_AfResult 0xc1a3 #define PTP_EC_CANON_EOS_CTGInfoCheckComplete 0xc1a4 #define PTP_EC_CANON_EOS_OLCInfoChanged 0xc1a5 +#define PTP_EC_CANON_EOS_ObjectAddedUnknown 0xc1a7 +#define PTP_EC_CANON_EOS_RequestObjectTransferNew 0xc1a9 #define PTP_EC_CANON_EOS_RequestObjectTransferFTP 0xc1f1 /* Nikon extension Event Codes */ @@ -822,7 +878,7 @@ typedef struct _PTPIPHeader PTPIPHeader; /* Sony */ #define PTP_EC_Sony_ObjectAdded 0xC201 -/* c202 ... unclear. also called with object id? */ +#define PTP_EC_Sony_ObjectRemoved 0xC202 #define PTP_EC_Sony_PropertyChanged 0xC203 /* MTP Event codes */ @@ -830,6 +886,10 @@ typedef struct _PTPIPHeader PTPIPHeader; #define PTP_EC_MTP_ObjectPropDescChanged 0xC802 #define PTP_EC_MTP_ObjectReferencesChanged 0xC803 +#define PTP_EC_PARROT_Status 0xC201 +#define PTP_EC_PARROT_MagnetoCalibrationStatus 0xC202 + + /* constants for GetObjectHandles */ #define PTP_GOH_ALL_STORAGE 0xffffffff #define PTP_GOH_ALL_FORMATS 0x00000000 @@ -1237,11 +1297,16 @@ struct _PTPNIKONWifiProfile { typedef struct _PTPNIKONWifiProfile PTPNIKONWifiProfile; -#define PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN 0 -#define PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO 1 -#define PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER 2 -#define PTP_CANON_EOS_CHANGES_TYPE_PROPERTY 3 -#define PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS 4 +enum _PTPCanon_changes_types { + PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN, + PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO, + PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER, + PTP_CANON_EOS_CHANGES_TYPE_PROPERTY, + PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS, + PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO, + PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK, + PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED +}; struct _PTPCanon_New_Object { uint32_t oid; @@ -1249,7 +1314,7 @@ struct _PTPCanon_New_Object { }; struct _PTPCanon_changes_entry { - int type; + enum _PTPCanon_changes_types type; union { struct _PTPCanon_New_Object object; /* TYPE_OBJECTINFO */ char *info; @@ -1261,7 +1326,6 @@ typedef struct _PTPCanon_changes_entry P typedef struct _PTPCanon_Property { uint32_t size; - uint32_t type; uint32_t proptype; unsigned char *data; @@ -1666,6 +1730,7 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_NIKON_RemoteMode 0xD035 #define PTP_DPC_NIKON_VideoMode 0xD036 #define PTP_DPC_NIKON_EffectMode 0xD037 +#define PTP_DPC_NIKON_1_Mode 0xD038 #define PTP_DPC_NIKON_CSMMenuBankSelect 0xD040 #define PTP_DPC_NIKON_MenuBankNameA 0xD041 #define PTP_DPC_NIKON_MenuBankNameB 0xD042 @@ -1750,6 +1815,7 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_NIKON_MovFileSlot 0xD0A3 #define PTP_DPC_NIKON_MovRecProhibitCondition 0xD0A4 #define PTP_DPC_NIKON_ManualMovieSetting 0xD0A6 +#define PTP_DPC_NIKON_MovQuality 0xD0A7 #define PTP_DPC_NIKON_LiveViewScreenDisplaySetting 0xD0B2 #define PTP_DPC_NIKON_MonitorOffDelay 0xD0B3 #define PTP_DPC_NIKON_Bracketing 0xD0C0 @@ -1861,6 +1927,10 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_NIKON_LiveViewStatus 0xD1A2 #define PTP_DPC_NIKON_LiveViewImageZoomRatio 0xD1A3 #define PTP_DPC_NIKON_LiveViewProhibitCondition 0xD1A4 +#define PTP_DPC_NIKON_MovieShutterSpeed 0xD1A8 +#define PTP_DPC_NIKON_MovieFNumber 0xD1A9 +#define PTP_DPC_NIKON_MovieISO 0xD1AA +#define PTP_DPC_NIKON_LiveViewMovieMode 0xD1AC /* ? */ #define PTP_DPC_NIKON_ExposureDisplayStatus 0xD1B0 #define PTP_DPC_NIKON_ExposureIndicateStatus 0xD1B1 #define PTP_DPC_NIKON_InfoDispErrStatus 0xD1B2 @@ -1884,6 +1954,8 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_NIKON_ActiveSlot 0xD1F2 #define PTP_DPC_NIKON_ActivePicCtrlItem 0xD200 #define PTP_DPC_NIKON_ChangePicCtrlItem 0xD201 +#define PTP_DPC_NIKON_MovieNrHighISO 0xD236 + /* Nikon V1 (or WU adapter?) Trace */ /* d241 - gets string "Nikon_WU2_0090B5123C61" */ @@ -1892,11 +1964,22 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_NIKON_D244 0xD244 /* d247 - gets 3 bytes 0x01 0x00 0x00 */ #define PTP_DPC_NIKON_D247 0xD247 +/* S9700 */ +#define PTP_DPC_NIKON_GUID 0xD24F /* d250 - gets a string "0000123C61" */ #define PTP_DPC_NIKON_D250 0xD250 /* d251 - gets a 0x0100000d */ #define PTP_DPC_NIKON_D251 0xD251 +/* this is irregular, as it should be -0x5000 or 0xD000 based */ +#define PTP_DPC_NIKON_1_ISO 0xF002 +#define PTP_DPC_NIKON_1_ImageCompression 0xF009 +#define PTP_DPC_NIKON_1_ImageSize 0xF00A +#define PTP_DPC_NIKON_1_WhiteBalance 0xF00C +#define PTP_DPC_NIKON_1_LongExposureNoiseReduction 0xF00D +#define PTP_DPC_NIKON_1_HiISONoiseReduction 0xF00E +#define PTP_DPC_NIKON_1_ActiveDLighting 0xF00F +#define PTP_DPC_NIKON_1_MovQuality 0xF01C /* Fuji specific */ #define PTP_DPC_FUJI_ColorTemperature 0xD017 @@ -2019,10 +2102,15 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_SONY_ColorTemp 0xD20F #define PTP_DPC_SONY_CCFilter 0xD210 #define PTP_DPC_SONY_AspectRatio 0xD211 +#define PTP_DPC_SONY_FocusFound 0xD213 /* seems to be signaled (1->2) when focus is achieved */ +#define PTP_DPC_SONY_ObjectInMemory 0xD215 /* used to signal when to retrieve new object */ #define PTP_DPC_SONY_ExposeIndex 0xD216 +#define PTP_DPC_SONY_BatteryLevel 0xD218 #define PTP_DPC_SONY_PictureEffect 0xD21B #define PTP_DPC_SONY_ABFilter 0xD21C #define PTP_DPC_SONY_ISO 0xD21E /* ? */ +#define PTP_DPC_SONY_AutoFocus 0xD2C1 /* ? half-press */ +#define PTP_DPC_SONY_Capture 0xD2C2 /* ? full-press */ /* also seen: D2C3 D2C4 */ /* semi control opcodes */ #define PTP_DPC_SONY_Movie 0xD2C8 /* ? */ @@ -2059,6 +2147,34 @@ typedef struct _PTPCanonEOSDeviceInfo { #define PTP_DPC_CASIO_UNKNOWN_17 0xD030 #define PTP_DPC_CASIO_UNKNOWN_18 0xD080 +#define PTP_DPC_RICOH_ShutterSpeed 0xD00F + +/* https://github.com/Parrot-Developers/sequoia-ptpy */ +#define PTP_DPC_PARROT_PhotoSensorEnableMask 0xD201 +#define PTP_DPC_PARROT_PhotoSensorsKeepOn 0xD202 +#define PTP_DPC_PARROT_MultispectralImageSize 0xD203 +#define PTP_DPC_PARROT_MainBitDepth 0xD204 +#define PTP_DPC_PARROT_MultispectralBitDepth 0xD205 +#define PTP_DPC_PARROT_HeatingEnable 0xD206 +#define PTP_DPC_PARROT_WifiStatus 0xD207 +#define PTP_DPC_PARROT_WifiSSID 0xD208 +#define PTP_DPC_PARROT_WifiEncryptionType 0xD209 +#define PTP_DPC_PARROT_WifiPassphrase 0xD20A +#define PTP_DPC_PARROT_WifiChannel 0xD20B +#define PTP_DPC_PARROT_Localization 0xD20C +#define PTP_DPC_PARROT_WifiMode 0xD20D +#define PTP_DPC_PARROT_AntiFlickeringFrequency 0xD210 +#define PTP_DPC_PARROT_DisplayOverlayMask 0xD211 +#define PTP_DPC_PARROT_GPSInterval 0xD212 +#define PTP_DPC_PARROT_MultisensorsExposureMeteringMode 0xD213 +#define PTP_DPC_PARROT_MultisensorsExposureTime 0xD214 +#define PTP_DPC_PARROT_MultisensorsExposureProgramMode 0xD215 +#define PTP_DPC_PARROT_MultisensorsExposureIndex 0xD216 +#define PTP_DPC_PARROT_MultisensorsIrradianceGain 0xD217 +#define PTP_DPC_PARROT_MultisensorsIrradianceIntegrationTime 0xD218 +#define PTP_DPC_PARROT_OverlapRate 0xD219 + + /* MTP specific Object Properties */ #define PTP_OPC_StorageID 0xDC01 #define PTP_OPC_ObjectFormat 0xDC02 @@ -2273,7 +2389,7 @@ typedef struct _PTPDataHandler { * This functions take PTP oriented arguments and send them over an * appropriate data layer doing byteorder conversion accordingly. */ -typedef uint16_t (* PTPIOSendReq) (PTPParams* params, PTPContainer* req); +typedef uint16_t (* PTPIOSendReq) (PTPParams* params, PTPContainer* req, int dataphase); typedef uint16_t (* PTPIOSendData) (PTPParams* params, PTPContainer* ptp, uint64_t size, PTPDataHandler*getter); @@ -2319,6 +2435,12 @@ struct _PTPDeviceProperty { }; typedef struct _PTPDeviceProperty PTPDeviceProperty; +/* Transaction data phase description, internal flags to sendreq / transaction driver. */ +#define PTP_DP_NODATA 0x0000 /* no data phase */ +#define PTP_DP_SENDDATA 0x0001 /* sending data */ +#define PTP_DP_GETDATA 0x0002 /* receiving data */ +#define PTP_DP_DATA_MASK 0x00ff /* data phase mask */ + struct _PTPParams { /* device flags */ uint32_t device_flags; @@ -2333,6 +2455,7 @@ struct _PTPParams { PTPIOGetResp getresp_func; PTPIOGetData getdata_func; PTPIOGetResp event_check; + PTPIOGetResp event_check_queue; PTPIOGetResp event_wait; PTPIOCancelReq cancelreq_func; @@ -2348,6 +2471,9 @@ struct _PTPParams { /* ptp session ID */ uint32_t session_id; + /* used for open capture */ + uint32_t opencapture_transid; + /* PTP IO: if we have MTP style split header/data transfers */ int split_header_data; int ocs64; /* 64bit objectsize */ @@ -2365,6 +2491,13 @@ struct _PTPParams { /* live view enabled */ int inliveview; + /* PTP: caching time for properties, default 2 */ + int cachetime; + + /* PTP: Storage Caching */ + PTPStorageIDs storageids; + int storagechanged; + /* PTP: Device Property Caching */ PTPDeviceProperty *deviceproperties; unsigned int nrofdeviceproperties; @@ -2383,6 +2516,8 @@ struct _PTPParams { /* PTP: Nikon specifics */ int controlmode; + int event90c7works; + int deletesdramfails; /* PTP: Wifi profiles */ uint8_t wifi_profiles_version; @@ -2401,7 +2536,7 @@ struct _PTPParams { char *olympus_reply; struct _PTPParams *outer_params; -#ifdef HAVE_ICONV +#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H) /* PTP: iconv converters */ iconv_t cd_locale_to_ucs2; iconv_t cd_ucs2_to_locale; @@ -2414,15 +2549,20 @@ struct _PTPParams { uint16_t response_packet_size; }; +/* Asynchronous event callback */ +typedef void (*PTPEventCbFn)(PTPParams *params, uint16_t code, PTPContainer *event, void *user_data); + /* last, but not least - ptp functions */ uint16_t ptp_usb_sendreq (PTPParams* params, PTPContainer* req); uint16_t ptp_usb_senddata (PTPParams* params, PTPContainer* ptp, uint64_t size, PTPDataHandler *handler); uint16_t ptp_usb_getresp (PTPParams* params, PTPContainer* resp); uint16_t ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler); -uint16_t ptp_usb_event_check (PTPParams* params, PTPContainer* event); +uint16_t ptp_usb_event_async (PTPParams *params, PTPEventCbFn cb, void *user_data); uint16_t ptp_usb_event_wait (PTPParams* params, PTPContainer* event); +uint16_t ptp_usb_event_check (PTPParams* params, PTPContainer* event); +uint16_t ptp_usb_event_check_queue (PTPParams* params, PTPContainer* event); uint16_t ptp_usb_control_get_extended_event_data (PTPParams *params, char *buffer, int *size); uint16_t ptp_usb_control_device_reset_request (PTPParams *params); @@ -2431,7 +2571,7 @@ uint16_t ptp_usb_control_cancel_request int ptp_ptpip_connect (PTPParams* params, const char *port); -uint16_t ptp_ptpip_sendreq (PTPParams* params, PTPContainer* req); +uint16_t ptp_ptpip_sendreq (PTPParams* params, PTPContainer* req, int dataphase); uint16_t ptp_ptpip_senddata (PTPParams* params, PTPContainer* ptp, uint64_t size, PTPDataHandler *handler); uint16_t ptp_ptpip_getresp (PTPParams* params, PTPContainer* resp); @@ -2439,6 +2579,7 @@ uint16_t ptp_ptpip_getdata (PTPParams* p PTPDataHandler *handler); uint16_t ptp_ptpip_event_wait (PTPParams* params, PTPContainer* event); uint16_t ptp_ptpip_event_check (PTPParams* params, PTPContainer* event); +uint16_t ptp_ptpip_event_check_queue (PTPParams* params, PTPContainer* event); uint16_t ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo); @@ -2464,6 +2605,16 @@ uint16_t ptp_transaction (PTPParams* par * Return values: Some PTP_RC_* code. **/ #define ptp_closesession(params) ptp_generic_no_data(params,PTP_OC_CloseSession,0) + +/** + * ptp_powerdown: + * params: PTPParams* + * + * Powers down device. + * + * Return values: Some PTP_RC_* code. + **/ +#define ptp_powerdown(params) ptp_generic_no_data(params,PTP_OC_PowerDown,0) /** * ptp_resetdevice: * params: PTPParams* @@ -2505,11 +2656,16 @@ uint16_t ptp_getobjectinfo (PTPParams *p uint16_t ptp_getobject (PTPParams *params, uint32_t handle, unsigned char** object); +uint16_t ptp_getobject_with_size (PTPParams *params, uint32_t handle, + unsigned char** object, unsigned int *size); uint16_t ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd); uint16_t ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler*); uint16_t ptp_getpartialobject (PTPParams* params, uint32_t handle, uint32_t offset, uint32_t maxbytes, unsigned char** object, uint32_t *len); +uint16_t ptp_getpartialobject_to_handler (PTPParams* params, uint32_t handle, uint32_t offset, + uint32_t maxbytes, PTPDataHandler *handler); + uint16_t ptp_getthumb (PTPParams *params, uint32_t handle, unsigned char** object, unsigned int *len); @@ -2550,6 +2706,9 @@ uint16_t ptp_sendobject_from_handler (P **/ #define ptp_initiatecapture(params,storageid,ofc) ptp_generic_no_data(params,PTP_OC_InitiateCapture,2,storageid,ofc) +#define ptp_initiateopencapture(params,storageid,ofc) ptp_generic_no_data(params,PTP_OC_InitiateOpenCapture,2,storageid,ofc) +#define ptp_terminateopencapture(params,transid) ptp_generic_no_data(params,PTP_OC_TerminateOpenCapture,1,transid) + uint16_t ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *devicepropertydesc); uint16_t ptp_generic_getdevicepropdesc (PTPParams *params, uint16_t propcode, @@ -2567,6 +2726,8 @@ uint16_t ptp_getfilesystemmanifest (PTPP uint16_t ptp_check_event (PTPParams *params); +uint16_t ptp_check_event_queue (PTPParams *params); +uint16_t ptp_wait_event (PTPParams *params); uint16_t ptp_add_event (PTPParams *params, PTPContainer *evt); int ptp_get_one_event (PTPParams *params, PTPContainer *evt); uint16_t ptp_check_eos_events (PTPParams *params); @@ -2847,6 +3008,7 @@ uint16_t ptp_canon_get_directory (PTPPar * **/ #define ptp_canon_setobjectarchive(params,oid,flags) ptp_generic_no_data(params,PTP_OC_CANON_SetObjectArchive,2,oid,flags) +#define ptp_canon_eos_setobjectattributes(params,oid,flags) ptp_generic_no_data(params,PTP_OC_CANON_EOS_SetObjectAttributes,2,oid,flags) uint16_t ptp_canon_get_customize_data (PTPParams* params, uint32_t themenr, unsigned char **data, unsigned int *size); uint16_t ptp_canon_getpairinginfo (PTPParams* params, uint32_t nr, unsigned char**, unsigned int*); @@ -2895,6 +3057,8 @@ uint16_t ptp_sony_setdevicecontrolvaluea PTPPropertyValue* value, uint16_t datatype); uint16_t ptp_sony_setdevicecontrolvalueb (PTPParams* params, uint16_t propcode, PTPPropertyValue* value, uint16_t datatype); +uint16_t ptp_sony_9280 (PTPParams* params, uint32_t additional, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t data4, uint8_t x, uint8_t y); +uint16_t ptp_sony_9281 (PTPParams* params, uint32_t param1); /** * ptp_nikon_deletewifiprofile: * @@ -2990,6 +3154,17 @@ uint16_t ptp_sony_setdevicecontrolvalueb **/ #define ptp_canon_eos_afdrive(params) ptp_generic_no_data(params,PTP_OC_CANON_EOS_DoAf,0) /** + * ptp_canon_eos_afcancel: + * + * This command cancels the lens autofocus. + * + * params: PTPParams* + * + * Return values: Some PTP_RC_* code. + * + **/ +#define ptp_canon_eos_afcancel(params) ptp_generic_no_data(params,PTP_OC_CANON_EOS_AfCancel,0) +/** * ptp_canon_eos_zoom: * * This command runs (drives) the lens autofocus. @@ -3128,17 +3303,17 @@ uint16_t ptp_mtp_getobjectpropssupported uint16_t ptp_android_getpartialobject64 (PTPParams* params, uint32_t handle, uint64_t offset, uint32_t maxbytes, unsigned char** object, uint32_t *len); -#define ptp_android_begineditobject(params,handle) ptp_generic_no_data (params, PTP_OC_ANDROID_BeginEditObject, 1, handle); -#define ptp_android_truncate(params,handle,offset) ptp_generic_no_data (params, PTP_OC_ANDROID_TruncateObject, 3, handle, (offset & 0xFFFFFFFF), (offset >> 32)); +#define ptp_android_begineditobject(params,handle) ptp_generic_no_data (params, PTP_OC_ANDROID_BeginEditObject, 1, handle) +#define ptp_android_truncate(params,handle,offset) ptp_generic_no_data (params, PTP_OC_ANDROID_TruncateObject, 3, handle, (offset & 0xFFFFFFFF), (offset >> 32)) uint16_t ptp_android_sendpartialobject (PTPParams *params, uint32_t handle, uint64_t offset, unsigned char *object, uint32_t len); -#define ptp_android_endeditobject(params,handle) ptp_generic_no_data (params, PTP_OC_ANDROID_EndEditObject, 1, handle); +#define ptp_android_endeditobject(params,handle) ptp_generic_no_data (params, PTP_OC_ANDROID_EndEditObject, 1, handle) uint16_t ptp_olympus_getdeviceinfo (PTPParams*, PTPDeviceInfo*); -#define ptp_olympus_setcameracontrolmode(params,p1) ptp_generic_no_data (params, PTP_OC_OLYMPUS_SetCameraControlMode, 1, p1); -uint16_t ptp_olympus_opensession (PTPParams*, unsigned char**, unsigned long *); -#define ptp_olympus_capture(params,p1) ptp_generic_no_data (params, PTP_OC_OLYMPUS_Capture, 1, p1); -uint16_t ptp_olympus_getcameraid (PTPParams*, unsigned char**, unsigned long *); +#define ptp_olympus_setcameracontrolmode(params,p1) ptp_generic_no_data (params, PTP_OC_OLYMPUS_SetCameraControlMode, 1, p1) +uint16_t ptp_olympus_opensession (PTPParams*, unsigned char**, unsigned int *); +#define ptp_olympus_capture(params,p1) ptp_generic_no_data (params, PTP_OC_OLYMPUS_Capture, 1, p1) +uint16_t ptp_olympus_getcameraid (PTPParams*, unsigned char**, unsigned int *); /* Non PTP protocol functions */ static inline int @@ -3163,26 +3338,25 @@ void ptp_free_devicepropvalue (uint16_t, void ptp_free_objectinfo (PTPObjectInfo *oi); void ptp_free_object (PTPObject *oi); -const char *ptp_strerror(uint16_t error); -void ptp_perror (PTPParams* params, uint16_t error); +const char *ptp_strerror (uint16_t ret, uint16_t vendor); void ptp_debug (PTPParams *params, const char *format, ...); void ptp_error (PTPParams *params, const char *format, ...); -const char* -ptp_get_property_description(PTPParams* params, uint16_t dpc); +const char* ptp_get_property_description(PTPParams* params, uint16_t dpc); + +const char* ptp_get_opcode_name(PTPParams* params, uint16_t opcode); int ptp_render_property_value(PTPParams* params, uint16_t dpc, PTPDevicePropDesc *dpd, unsigned int length, char *out); int ptp_render_ofc(PTPParams* params, uint16_t ofc, int spaceleft, char *txt); -int ptp_render_opcode(PTPParams* params, uint16_t opcode, int spaceleft, char *txt); int ptp_render_mtp_propname(uint16_t propid, int spaceleft, char *txt); MTPProperties *ptp_get_new_object_prop_entry(MTPProperties **props, int *nrofprops); void ptp_destroy_object_prop(MTPProperties *prop); void ptp_destroy_object_prop_list(MTPProperties *props, int nrofprops); MTPProperties *ptp_find_object_prop_in_cache(PTPParams *params, uint32_t const handle, uint32_t const attribute_id); -void ptp_remove_object_from_cache(PTPParams *params, uint32_t handle); +uint16_t ptp_remove_object_from_cache(PTPParams *params, uint32_t handle); uint16_t ptp_add_object_to_cache(PTPParams *params, uint32_t handle); uint16_t ptp_object_want (PTPParams *, uint32_t handle, unsigned int want, PTPObject**retob); void ptp_objects_sort (PTPParams *); @@ -3236,7 +3410,7 @@ typedef struct { uint16_t ptp_chdk_get_memory(PTPParams* params, int start, int num, unsigned char **); uint16_t ptp_chdk_set_memory_long(PTPParams* params, int addr, int val); int ptp_chdk_upload(PTPParams* params, char *local_fn, char *remote_fn); -int ptp_chdk_download(PTPParams* params, char *remote_fn, char *local_fn); +uint16_t ptp_chdk_download(PTPParams* params, char *remote_fn, PTPDataHandler *handler); /* remote capture */ uint16_t ptp_chdk_rcisready(PTPParams* params, int *isready,int *imgnum);