ptp-pack.c

来自「Media transfer protocol implementation o」· C语言 代码 · 共 1,202 行 · 第 1/3 页

C
1,202
字号
	}*/	/*	 *XXX Fake date.	 * for example Kodak sets Capture date on the basis of EXIF data.	 * Spec says that this field is from perspective of Initiator.	 */#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/	capturedatelen=strlen(capture_date);	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],		capturedatelen+1);	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];	}	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],		capturedatelen+1);	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=		  capture_date[i];	}#endif	/* XXX this function should return dataset length */		*oidataptr=oidata;	return (PTP_oi_Filename+(filenamelen+1)*2+(capturedatelen+1)*4);}static inline voidptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len){	uint8_t filenamelen;	uint8_t capturedatelen;	char *capture_date;	char tmp[16];	struct tm tm;	memset(&tm,0,sizeof(tm));	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);	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);	capture_date = ptp_unpack_string(params, data,		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);	/* subset of ISO 8601, without '.s' tenths of second and 	 * time zone	 */	if (capturedatelen>15)	{		strncpy (tmp, capture_date, 4);		tmp[4] = 0;		tm.tm_year=atoi (tmp) - 1900;		strncpy (tmp, capture_date + 4, 2);		tmp[2] = 0;		tm.tm_mon = atoi (tmp) - 1;		strncpy (tmp, capture_date + 6, 2);		tmp[2] = 0;		tm.tm_mday = atoi (tmp);		strncpy (tmp, capture_date + 9, 2);		tmp[2] = 0;		tm.tm_hour = atoi (tmp);		strncpy (tmp, capture_date + 11, 2);		tmp[2] = 0;		tm.tm_min = atoi (tmp);		strncpy (tmp, capture_date + 13, 2);		tmp[2] = 0;		tm.tm_sec = atoi (tmp);		oi->CaptureDate=mktime (&tm);	}	free(capture_date);	/* now it's modification date ;) */	capture_date = ptp_unpack_string(params, data,		PTP_oi_filenamelen+filenamelen*2		+capturedatelen*2+2,&capturedatelen);	if (capturedatelen>15)	{		strncpy (tmp, capture_date, 4);		tmp[4] = 0;		tm.tm_year=atoi (tmp) - 1900;		strncpy (tmp, capture_date + 4, 2);		tmp[2] = 0;		tm.tm_mon = atoi (tmp) - 1;		strncpy (tmp, capture_date + 6, 2);		tmp[2] = 0;		tm.tm_mday = atoi (tmp);		strncpy (tmp, capture_date + 9, 2);		tmp[2] = 0;		tm.tm_hour = atoi (tmp);		strncpy (tmp, capture_date + 11, 2);		tmp[2] = 0;		tm.tm_min = atoi (tmp);		strncpy (tmp, capture_date + 13, 2);		tmp[2] = 0;		tm.tm_sec = atoi (tmp);		oi->ModificationDate=mktime (&tm);	}	free(capture_date);}/* Custom Type Value Assignement (without Length) macro frequently used below */#define CTVAL(target,func) {			\	if (total - *offset < sizeof(target))	\		return 0;			\	target = func(&data[*offset]);		\	*offset += sizeof(target);		\}#define RARR(val,member,func)	{			\	int n,j;					\	if (total - *offset < sizeof(uint32_t))		\		return 0;				\	n = dtoh32a (&data[*offset]);			\	*offset += sizeof(uint32_t);			\							\	val->a.count = n;				\	val->a.v = malloc(sizeof(val->a.v[0])*n);	\	if (!val->a.v) return 0;			\	for (j=0;j<n;j++)				\		CTVAL(val->a.v[j].member, func);	\}static inline intptp_unpack_DPV (	PTPParams *params, unsigned char* data, int *offset, int total,	PTPPropertyValue* value, uint16_t datatype) {	switch (datatype) {	case PTP_DTC_INT8:		CTVAL(value->i8,dtoh8a);		break;	case PTP_DTC_UINT8:		CTVAL(value->u8,dtoh8a);		break;	case PTP_DTC_INT16:		CTVAL(value->i16,dtoh16a);		break;	case PTP_DTC_UINT16:		CTVAL(value->u16,dtoh16a);		break;	case PTP_DTC_INT32:		CTVAL(value->i32,dtoh32a);		break;	case PTP_DTC_UINT32:		CTVAL(value->u32,dtoh32a);		break;	case PTP_DTC_AINT8:		RARR(value,i8,dtoh8a);		break;	case PTP_DTC_AUINT8:		RARR(value,u8,dtoh8a);		break;	case PTP_DTC_AUINT16:		RARR(value,u16,dtoh16a);		break;	case PTP_DTC_AINT16:		RARR(value,i16,dtoh16a);		break;	case PTP_DTC_AUINT32:		RARR(value,u32,dtoh32a);		break;	case PTP_DTC_AINT32:		RARR(value,i32,dtoh32a);		break;	/* XXX: other int types are unimplemented */	/* XXX: other int arrays are unimplemented also */	case PTP_DTC_STR: {		uint8_t len;		/* XXX: max size */		value->str = ptp_unpack_string(params,data,*offset,&len);		*offset += len*2+1;		if (!value->str)			return 0;		break;	}	}	return 1;}/* Device Property pack/unpack */#define PTP_dpd_DevicePropertyCode	0#define PTP_dpd_DataType		2#define PTP_dpd_GetSet			4#define PTP_dpd_FactoryDefaultValue	5static inline intptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen){	int offset=0, ret;	memset (dpd, 0, sizeof(*dpd));	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);	offset = PTP_dpd_FactoryDefaultValue;	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);	if (!ret) goto outofmemory;	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);	if (!ret) goto outofmemory;	/* if offset==0 then Data Type format is not supported by this	   code or the Data Type is a string (with two empty strings as	   values). In both cases Form Flag should be set to 0x00 and FORM is	   not present. */	dpd->FormFlag=PTP_DPFF_None;	if (offset==PTP_dpd_FactoryDefaultValue)		return 1;	dpd->FormFlag=dtoh8a(&data[offset]);	offset+=sizeof(uint8_t);	switch (dpd->FormFlag) {	case PTP_DPFF_Range:		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);		if (!ret) goto outofmemory;		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);		if (!ret) goto outofmemory;		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);		if (!ret) goto outofmemory;		break;	case PTP_DPFF_Enumeration: {		int i;#define N	dpd->FORM.Enum.NumberOfValues		N = dtoh16a(&data[offset]);		offset+=sizeof(uint16_t);		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));		if (!dpd->FORM.Enum.SupportedValue)			goto outofmemory;		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));		for (i=0;i<N;i++) {			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);			/* Slightly different handling here. The HP PhotoSmart 120			 * specifies an enumeration with N in wrong endian			 * 00 01 instead of 01 00, so we count the enum just until the			 * the end of the packet.			 */			if (!ret) {				if (!i)					goto outofmemory;				dpd->FORM.Enum.NumberOfValues = i;				break;			}		}		}	}#undef N	return 1;outofmemory:	ptp_free_devicepropdesc(dpd);	return 0;}/* (MTP) Object Property pack/unpack */#define PTP_opd_ObjectPropertyCode	0#define PTP_opd_DataType		2#define PTP_opd_GetSet			4#define PTP_opd_FactoryDefaultValue	5static inline intptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen){	int offset=0, ret;	memset (opd, 0, sizeof(*opd));	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);	offset = PTP_opd_FactoryDefaultValue;	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);	if (!ret) goto outofmemory;	opd->GroupCode=dtoh32a(&data[offset]);	offset+=sizeof(uint32_t);	opd->FormFlag=dtoh8a(&data[offset]);	offset+=sizeof(uint8_t);	switch (opd->FormFlag) {	case PTP_OPFF_Range:		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);		if (!ret) goto outofmemory;		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);		if (!ret) goto outofmemory;		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);		if (!ret) goto outofmemory;		break;	case PTP_OPFF_Enumeration: {		int i;#define N	opd->FORM.Enum.NumberOfValues		N = dtoh16a(&data[offset]);		offset+=sizeof(uint16_t);		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));		if (!opd->FORM.Enum.SupportedValue)			goto outofmemory;		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));		for (i=0;i<N;i++) {			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);			/* Slightly different handling here. The HP PhotoSmart 120			 * specifies an enumeration with N in wrong endian			 * 00 01 instead of 01 00, so we count the enum just until the			 * the end of the packet.			 */			if (!ret) {				if (!i)					goto outofmemory;				opd->FORM.Enum.NumberOfValues = i;				break;			}		}#undef N		}	}	return 1;outofmemory:	ptp_free_objectpropdesc(opd);	return 0;}static inline uint32_tptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype){	unsigned char* dpv=NULL;	uint32_t size=0;	int	i;	switch (datatype) {	case PTP_DTC_INT8:		size=sizeof(int8_t);		dpv=malloc(size);		htod8a(dpv,value->i8);		break;	case PTP_DTC_UINT8:		size=sizeof(uint8_t);		dpv=malloc(size);		htod8a(dpv,value->u8);		break;	case PTP_DTC_INT16:		size=sizeof(int16_t);		dpv=malloc(size);		htod16a(dpv,value->i16);		break;	case PTP_DTC_UINT16:		size=sizeof(uint16_t);		dpv=malloc(size);		htod16a(dpv,value->u16);		break;	case PTP_DTC_INT32:		size=sizeof(int32_t);		dpv=malloc(size);		htod32a(dpv,value->i32);		break;	case PTP_DTC_UINT32:		size=sizeof(uint32_t);		dpv=malloc(size);		htod32a(dpv,value->u32);		break;	case PTP_DTC_AUINT8:		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);		dpv=malloc(size);		htod32a(dpv,value->a.count);		for (i=0;i<value->a.count;i++)			htod8a(&dpv[4+i],value->a.v[i].u8);		break;	case PTP_DTC_AINT8:		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);		dpv=malloc(size);		htod32a(dpv,value->a.count);		for (i=0;i<value->a.count;i++)			htod8a(&dpv[4+i],value->a.v[i].i8);		break;	case PTP_DTC_AUINT16:		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);		dpv=malloc(size);		htod32a(dpv,value->a.count);		for (i=0;i<value->a.count;i++)			htod16a(&dpv[4+i],value->a.v[i].u16);		break;	case PTP_DTC_AINT16:		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?