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 + -
显示快捷键?