1 /******************************************************************************************************************************************
2 * 文件名称: usbh_mtp.c
3 * 功能说明: This file includes the PTP operations layer.
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2020年11月3日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include <string.h>
22 #include "SWM341.h"
23 #include "usbh_core.h"
24 #include "usbh_mtp.h"
25 
26 
27 /******************************************************************************************************************************************
28 * 函数名称: PTP_GetDevicePropValue()
29 * 功能说明:
30 * 输    入: 无
31 * 输    出: 无
32 * 注意事项: 无
33 ******************************************************************************************************************************************/
PTP_GetDevicePropValue(USBH_Info_t * phost,uint32_t * offset,uint32_t total,PTP_PropertyValue_t * value,uint16_t datatype)34 void PTP_GetDevicePropValue(USBH_Info_t *phost, uint32_t *offset, uint32_t total, PTP_PropertyValue_t *value, uint16_t datatype)
35 {
36     uint8_t *data = USBH_MTP_Info.data_container.payload;
37     uint16_t len;
38     switch(datatype)
39     {
40     case PTP_DTC_INT8:
41         value->i8 = *(int8_t *)(void *) & (data[*offset]);
42         *offset += 1U;
43         break;
44 
45     case PTP_DTC_UINT8:
46         value->u8 = *(uint8_t *) & (data[*offset]);
47         *offset += 1U;
48         break;
49 
50     case PTP_DTC_INT16:
51         value->i16 = *(int16_t *)(void *) & (data[*offset]);
52         *offset += 2U;
53         break;
54 
55     case PTP_DTC_UINT16:
56         value->u16 = PTP_LE16(&(data[*offset]));
57         *offset += 2U;
58         break;
59 
60     case PTP_DTC_INT32:
61         value->i32 = *(int32_t *)(void *)(&(data[*offset]));
62         *offset += 4U;
63         break;
64 
65     case PTP_DTC_UINT32:
66         value->u32 = PTP_LE32(&(data[*offset]));
67         *offset += 4U;
68         break;
69 
70     case PTP_DTC_INT64:
71         value->i64 = *(int64_t *)(void *)(&(data[*offset]));
72         *offset += 8U;
73         break;
74 
75     case PTP_DTC_UINT64:
76         value->u64 = PTP_LE64(&(data[*offset]));
77         *offset += 8U;
78         break;
79 
80     case PTP_DTC_UINT128:
81         *offset += 16U;
82         break;
83 
84     case PTP_DTC_INT128:
85         *offset += 16U;
86         break;
87 
88     case PTP_DTC_STR:
89         PTP_GetString((uint8_t *)(void *)value->str, (uint8_t *) & (data[*offset]), &len);
90         *offset += (uint32_t)(len * 2U) + 1U;
91         break;
92 
93     default:
94         break;
95     }
96 }
97 
98 
99 /******************************************************************************************************************************************
100 * 函数名称: PTP_GetString()
101 * 功能说明:
102 * 输    入: 无
103 * 输    出: 无
104 * 注意事项: 无
105 ******************************************************************************************************************************************/
PTP_GetString(uint8_t * str,uint8_t * data,uint16_t * len)106 void PTP_GetString(uint8_t *str, uint8_t *data, uint16_t *len)
107 {
108     uint16_t strlength;
109     uint16_t idx;
110 
111     *len = data[0];
112     strlength = (uint16_t)(2U * (uint32_t)data[0]);
113     data ++; /* Adjust the offset ignoring the String Len */
114 
115     for (idx = 0U; idx < strlength; idx += 2U)
116     {
117         /* Copy Only the string and ignore the UNICODE ID, hence add the src */
118         *str = data[idx];
119         str++;
120     }
121     *str = 0U; /* mark end of string */
122 }
123 
124 
125 /******************************************************************************************************************************************
126 * 函数名称: PTP_GetArray16()
127 * 功能说明:
128 * 输    入: 无
129 * 输    出: 无
130 * 注意事项: 无
131 ******************************************************************************************************************************************/
PTP_GetArray16(uint16_t * array,uint8_t * data,uint32_t offset)132 uint32_t PTP_GetArray16(uint16_t *array, uint8_t *data, uint32_t offset)
133 {
134     uint32_t size, idx = 0U;
135 
136     size = PTP_LE32(&data[offset]);
137     while(size > idx)
138     {
139         array[idx] = (uint16_t)data[offset + (sizeof(uint16_t) * (idx + 2U))];
140         idx++;
141     }
142     return size;
143 }
144 
145 
146 /******************************************************************************************************************************************
147 * 函数名称: PTP_GetArray32()
148 * 功能说明:
149 * 输    入: 无
150 * 输    出: 无
151 * 注意事项: 无
152 ******************************************************************************************************************************************/
PTP_GetArray32(uint32_t * array,uint8_t * data,uint32_t offset)153 uint32_t PTP_GetArray32(uint32_t *array, uint8_t *data, uint32_t offset)
154 {
155     uint32_t size, idx = 0U;
156 
157     size = PTP_LE32(&data[offset]);
158     while(size > idx)
159     {
160         array[idx] = PTP_LE32(&data[offset + (sizeof(uint32_t) * (idx + 1U))]);
161         idx++;
162     }
163     return size;
164 }
165 
166 
167 /******************************************************************************************************************************************
168 * 函数名称: PTP_DecodeDeviceInfo()
169 * 功能说明:
170 * 输    入: 无
171 * 输    出: 无
172 * 注意事项: 无
173 ******************************************************************************************************************************************/
PTP_DecodeDeviceInfo(USBH_Info_t * phost,PTP_DeviceInfo_t * dev_info)174 void PTP_DecodeDeviceInfo(USBH_Info_t *phost, PTP_DeviceInfo_t *dev_info)
175 {
176     uint8_t *data = USBH_MTP_Info.data_container.payload;
177     uint32_t totallen;
178     uint16_t len;
179 
180     dev_info->StandardVersion = PTP_LE16(&data[PTP_di_StandardVersion]);
181     dev_info->VendorExtensionID = PTP_LE32(&data[PTP_di_VendorExtensionID]);
182     dev_info->VendorExtensionVersion = PTP_LE16(&data[PTP_di_VendorExtensionVersion]);
183     PTP_GetString(dev_info->VendorExtensionDesc, &data[PTP_di_VendorExtensionDesc], &len);
184 
185     totallen = (uint32_t)(len * 2U) + 1U;
186     dev_info->FunctionalMode = PTP_LE16(&data[PTP_di_FunctionalMode + totallen]);
187     dev_info->OperationsSupportedNbr = PTP_GetArray16((uint16_t *)(void *)&dev_info->OperationsSupported, data, PTP_di_OperationsSupported + totallen);
188 
189     totallen = totallen + (dev_info->OperationsSupportedNbr * sizeof(uint16_t)) + sizeof(uint32_t);
190     dev_info->EventsSupportedNbr = PTP_GetArray16((uint16_t *)(void *)&dev_info->EventsSupported, data, PTP_di_OperationsSupported + totallen);
191 
192     totallen = totallen + (dev_info->EventsSupportedNbr * sizeof(uint16_t)) + sizeof(uint32_t);
193     dev_info->DevicePropertiesSupportedNbr = PTP_GetArray16((uint16_t *)(void *)&dev_info->DevicePropertiesSupported, data, PTP_di_OperationsSupported + totallen);
194 
195     totallen = totallen + (dev_info->DevicePropertiesSupportedNbr * sizeof(uint16_t)) + sizeof(uint32_t);
196 
197     dev_info->CaptureFormatsNbr = PTP_GetArray16((uint16_t *)(void *)&dev_info->CaptureFormats, data, PTP_di_OperationsSupported + totallen);
198 
199     totallen = totallen + (dev_info->CaptureFormatsNbr * sizeof(uint16_t)) + sizeof(uint32_t);
200     dev_info->ImageFormatsNbr =  PTP_GetArray16((uint16_t *)(void *)&dev_info->ImageFormats, data, PTP_di_OperationsSupported + totallen);
201 
202     totallen = totallen + (dev_info->ImageFormatsNbr * sizeof(uint16_t)) + sizeof(uint32_t);
203     PTP_GetString(dev_info->Manufacturer, &data[PTP_di_OperationsSupported + totallen], &len);
204 
205     totallen += (uint32_t)(len * 2U) + 1U;
206     PTP_GetString(dev_info->Model, &data[PTP_di_OperationsSupported + totallen], &len);
207 
208     totallen += (uint32_t)(len * 2U) + 1U;
209     PTP_GetString(dev_info->DeviceVersion, &data[PTP_di_OperationsSupported + totallen], &len);
210 
211     totallen += (uint32_t)(len * 2U) + 1U;
212     PTP_GetString(dev_info->SerialNumber, &data[PTP_di_OperationsSupported + totallen], &len);
213 }
214 
215 
216 /******************************************************************************************************************************************
217 * 函数名称: PTP_DecodeStorageInfo()
218 * 功能说明:
219 * 输    入: 无
220 * 输    出: 无
221 * 注意事项: 无
222 ******************************************************************************************************************************************/
PTP_DecodeStorageInfo(USBH_Info_t * phost,PTP_StorageInfo_t * storage_info)223 void PTP_DecodeStorageInfo(USBH_Info_t *phost, PTP_StorageInfo_t *storage_info)
224 {
225     uint8_t *data = USBH_MTP_Info.data_container.payload;
226     uint16_t len;
227 
228     storage_info->StorageType = PTP_LE16(&data[PTP_si_StorageType]);
229     storage_info->FilesystemType = PTP_LE16(&data[PTP_si_FilesystemType]);
230     storage_info->AccessCapability = PTP_LE16(&data[PTP_si_AccessCapability]);
231     storage_info->MaxCapability = PTP_LE64(&data[PTP_si_MaxCapability]);
232     storage_info->FreeSpaceInBytes = PTP_LE64(&data[PTP_si_FreeSpaceInBytes]);
233     storage_info->FreeSpaceInImages = PTP_LE32(&data[PTP_si_FreeSpaceInImages]);
234 
235     PTP_GetString(storage_info->StorageDescription, &data[PTP_si_StorageDescription], &len);
236     PTP_GetString(storage_info->VolumeLabel, &data[PTP_si_StorageDescription + (len * 2U) + 1U], &len);
237 }
238 
239 
240 /******************************************************************************************************************************************
241 * 函数名称: PTP_DecodeObjectInfo()
242 * 功能说明:
243 * 输    入: 无
244 * 输    出: 无
245 * 注意事项: 无
246 ******************************************************************************************************************************************/
PTP_DecodeObjectInfo(USBH_Info_t * phost,PTP_ObjectInfo_t * object_info)247 void PTP_DecodeObjectInfo(USBH_Info_t *phost, PTP_ObjectInfo_t *object_info)
248 {
249     uint8_t *data = USBH_MTP_Info.data_container.payload;
250     uint16_t filenamelen;
251 
252     object_info->StorageID = PTP_LE32(&data[PTP_oi_StorageID]);
253     object_info->ObjectFormat = PTP_LE16(&data[PTP_oi_ObjectFormat]);
254     object_info->ProtectionStatus = PTP_LE16(&data[PTP_oi_ProtectionStatus]);
255     object_info->ObjectCompressedSize = PTP_LE64(&data[PTP_oi_ObjectCompressedSize]);
256 
257     /* For Samsung Galaxy */
258     if((data[PTP_oi_filenamelen] == 0U) && (data[PTP_oi_filenamelen + 4U] != 0U))
259     {
260         data += 4;
261     }
262     object_info->ThumbFormat = PTP_LE16(&data[PTP_oi_ThumbFormat]);
263     object_info->ThumbCompressedSize = PTP_LE32(&data[PTP_oi_ThumbCompressedSize]);
264     object_info->ThumbPixWidth = PTP_LE32(&data[PTP_oi_ThumbPixWidth]);
265     object_info->ThumbPixHeight = PTP_LE32(&data[PTP_oi_ThumbPixHeight]);
266     object_info->ImagePixWidth = PTP_LE32(&data[PTP_oi_ImagePixWidth]);
267     object_info->ImagePixHeight = PTP_LE32(&data[PTP_oi_ImagePixHeight]);
268     object_info->ImageBitDepth = PTP_LE32(&data[PTP_oi_ImageBitDepth]);
269     object_info->ParentObject = PTP_LE32(&data[PTP_oi_ParentObject]);
270     object_info->AssociationType = PTP_LE16(&data[PTP_oi_AssociationType]);
271     object_info->AssociationDesc = PTP_LE32(&data[PTP_oi_AssociationDesc]);
272     object_info->SequenceNumber = PTP_LE32(&data[PTP_oi_SequenceNumber]);
273     PTP_GetString(object_info->Filename, &data[PTP_oi_filenamelen], &filenamelen);
274 }
275 
276 
277 /******************************************************************************************************************************************
278 * 函数名称: PTP_DecodeObjectPropDesc()
279 * 功能说明:
280 * 输    入: 无
281 * 输    出: 无
282 * 注意事项: 无
283 ******************************************************************************************************************************************/
PTP_DecodeObjectPropDesc(USBH_Info_t * phost,PTP_ObjectPropDesc_t * opd,uint32_t opdlen)284 void PTP_DecodeObjectPropDesc(USBH_Info_t *phost, PTP_ObjectPropDesc_t *opd, uint32_t opdlen)
285 {
286     uint8_t *data = USBH_MTP_Info.data_container.payload;
287     uint32_t offset = 0U, i;
288 
289     opd->ObjectPropertyCode = PTP_LE16(&data[PTP_opd_ObjectPropertyCode]);
290     opd->DataType = PTP_LE16(&data[PTP_opd_DataType]);
291     opd->GetSet = *(uint8_t *)(&data[PTP_opd_GetSet]);
292 
293     offset = PTP_opd_FactoryDefaultValue;
294     PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
295 
296     opd->GroupCode = PTP_LE32(&data[offset]);
297     offset += sizeof(uint32_t);
298 
299     opd->FormFlag = *(uint8_t *)(&data[offset]);
300     offset += sizeof(uint8_t);
301 
302     switch(opd->FormFlag)
303     {
304     case PTP_OPFF_Range:
305         PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
306         PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
307         PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
308         break;
309 
310     case PTP_OPFF_Enumeration:
311         opd->FORM.Enum.NumberOfValues = PTP_LE16(&data[offset]);
312         offset += sizeof(uint16_t);
313 
314         for(i = 0U; i < opd->FORM.Enum.NumberOfValues ; i++)
315         {
316             PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
317         }
318         break;
319 
320     default:
321         break;
322     }
323 }
324 
325 
326 /******************************************************************************************************************************************
327 * 函数名称: PTP_DecodeObjectPropList()
328 * 功能说明:
329 * 输    入: 无
330 * 输    出: 无
331 * 注意事项: 无
332 ******************************************************************************************************************************************/
PTP_DecodeObjectPropList(USBH_Info_t * phost,MTP_Properties_t * props,uint32_t len)333 uint32_t PTP_DecodeObjectPropList(USBH_Info_t *phost, MTP_Properties_t *props, uint32_t len)
334 {
335     uint8_t *data = USBH_MTP_Info.data_container.payload;
336     uint32_t prop_count;
337     uint32_t offset = 0U, i;
338 
339     prop_count = PTP_LE32(data);
340     if(prop_count == 0U)
341     {
342         return 0;
343     }
344 
345     data += sizeof(uint32_t);
346     len -= sizeof(uint32_t);
347 
348     for(i = 0U; i < prop_count; i++)
349     {
350         if(len <= 0U)
351         {
352             return 0;
353         }
354 
355         props[i].ObjectHandle = PTP_LE32(data);
356         data += sizeof(uint32_t);
357         len -= sizeof(uint32_t);
358 
359         props[i].property = PTP_LE16(data);
360         data += sizeof(uint16_t);
361         len -= sizeof(uint16_t);
362 
363         props[i].datatype = PTP_LE16(data);
364         data += sizeof(uint16_t);
365         len -= sizeof(uint16_t);
366 
367         offset = 0U;
368 
369         PTP_GetDevicePropValue(phost, &offset, len, &props[i].propval, props[i].datatype);
370 
371         data += offset;
372         len -= offset;
373     }
374 
375     return prop_count;
376 }
377