/** ****************************************************************************** * @file usbd_mtp_opt.c * @author MCD Application Team * @brief This file includes the PTP operations layer ****************************************************************************** * @attention * * Copyright (c) 2021 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_mtp_opt.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static uint8_t ObjInfo_buff[255]; static uint32_t objhandle; static uint16_t obj_format; static uint32_t storage_id; static MTP_DeviceInfoTypedef MTP_DeviceInfo; static MTP_StorageIDSTypeDef MTP_StorageIDS; static MTP_StorageInfoTypedef MTP_StorageInfo; static MTP_ObjectHandleTypeDef MTP_ObjectHandle; static MTP_ObjectInfoTypeDef MTP_ObjectInfo; static MTP_ObjectPropSuppTypeDef MTP_ObjectPropSupp; static MTP_ObjectPropDescTypeDef MTP_ObjectPropDesc; static MTP_PropertiesListTypedef MTP_PropertiesList; static MTP_RefTypeDef MTP_Ref; static MTP_PropertyValueTypedef MTP_PropertyValue; static MTP_FileNameTypeDef MTP_FileName; static MTP_DevicePropDescTypeDef MTP_DevicePropDesc; /* Private function prototypes -----------------------------------------------*/ static void MTP_Get_DeviceInfo(void); static void MTP_Get_StorageIDS(void); static void MTP_Get_PayloadContent(USBD_HandleTypeDef *pdev); static void MTP_Get_ObjectInfo(USBD_HandleTypeDef *pdev); static void MTP_Get_StorageInfo(USBD_HandleTypeDef *pdev); static void MTP_Get_ObjectHandle(USBD_HandleTypeDef *pdev); static void MTP_Get_ObjectPropSupp(void); static void MTP_Get_ObjectPropDesc(USBD_HandleTypeDef *pdev); static void MTP_Get_ObjectPropList(USBD_HandleTypeDef *pdev); static void MTP_Get_DevicePropDesc(void); static uint8_t *MTP_Get_ObjectPropValue(USBD_HandleTypeDef *pdev); static uint32_t MTP_build_data_propdesc(USBD_HandleTypeDef *pdev, MTP_ObjectPropDescTypeDef def); static uint32_t MTP_build_data_ObjInfo(USBD_HandleTypeDef *pdev, MTP_ObjectInfoTypeDef objinfo); static uint32_t MTP_build_data_proplist(USBD_HandleTypeDef *pdev, MTP_PropertiesListTypedef proplist, uint32_t idx); /* Private functions ---------------------------------------------------------*/ /** * @} */ /** * @brief USBD_MTP_OPT_CreateObjectHandle * Open a new session * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_CreateObjectHandle(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; if (hmtp->OperationsContainer.Param1 == 0U) /* Param1 == Session ID*/ { hmtp->ResponseCode = MTP_RESPONSE_INVALID_PARAMETER; } /* driver supports single session */ else if (hmtp->MTP_SessionState == MTP_SESSION_OPENED) { hmtp->ResponseCode = MTP_RESPONSE_SESSION_ALREADY_OPEN; } else { hmtp->ResponseCode = MTP_RESPONSE_OK; hmtp->MTP_SessionState = MTP_SESSION_OPENED; } hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->ResponseLength = MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; } /** * @brief USBD_MTP_OPT_GetDeviceInfo * Get all device information * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetDeviceInfo(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; if (hmtp->MTP_SessionState == MTP_SESSION_NOT_OPENED) /* no session opened */ { /* if GetDevice Info called outside a session then SessionID and Transaction_ID shall be 0x00000000*/ /* Param1 == session ID*/ if ((hmtp->OperationsContainer.Param1 == 0U) && (hmtp->OperationsContainer.trans_id == 0U)) { hmtp->ResponseCode = MTP_RESPONSE_OK; } else { hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->ResponseCode = MTP_RESPONSE_INVALID_PARAMETER; hmtp->GenericContainer.length = MTP_CONT_HEADER_SIZE; } } else { hmtp->ResponseCode = MTP_RESPONSE_OK; } if (hmtp->ResponseCode == MTP_RESPONSE_OK) { hmtp->GenericContainer.code = MTP_OP_GET_DEVICE_INFO; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_DeviceInfo) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; } } /** * @brief USBD_MTP_OPT_GetStorageIDS * Get Storage IDs * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetStorageIDS(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_STORAGE_IDS; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_StorageIDS) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetStorageInfo * Get Storage information * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetStorageInfo(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_STORAGE_INFO; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_StorageInfo) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectHandle * Get all object handles * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectHandle(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_HANDLES; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = hmtp->ResponseLength + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectInfo * Get all information about the object * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectInfo(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_INFO; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = hmtp->ResponseLength + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectReferences * Get object references * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectReferences(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_PROP_REFERENCES; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_Ref) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectPropSupp * Get all object properties supported * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectPropSupp(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_PROPS_SUPPORTED; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_ObjectPropSupp) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectPropDesc * Get all descriptions about object properties * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectPropDesc(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_PROP_DESC; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = hmtp->ResponseLength + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectPropList * Get the list of object properties * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectPropList(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_PROPLIST; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = hmtp->ResponseLength + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObjectPropValue * Get current value of the object property * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObjectPropValue(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_OBJECT_PROP_VALUE; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = hmtp->ResponseLength + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetObject * Get binary data from an object * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetObject(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; hmtp->GenericContainer.length = hmtpif->GetContainerLength(hmtp->OperationsContainer.Param1); hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_GetDevicePropDesc * Get The DevicePropDesc dataset * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_GetDevicePropDesc(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; hmtp->GenericContainer.code = MTP_OP_GET_DEVICE_PROP_DESC; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_DATA; (void)MTP_Get_PayloadContent(pdev); hmtp->ResponseLength = sizeof(MTP_DevicePropDesc) + MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_SendObject * Send object from host to MTP device * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_SendObject(USBD_HandleTypeDef *pdev, uint8_t *buff, uint32_t len) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; static uint32_t tmp = 0U; switch (hmtp->RECEIVE_DATA_STATUS) { case RECEIVE_IDLE_STATE: hmtp->RECEIVE_DATA_STATUS = RECEIVE_COMMAND_DATA; break; case RECEIVE_COMMAND_DATA: hmtp->RECEIVE_DATA_STATUS = RECEIVE_FIRST_DATA; break; case RECEIVE_FIRST_DATA: if ((uint16_t)len < (hmtp->MaxPcktLen - MTP_CONT_HEADER_SIZE)) { hmtp->GenericContainer.code = MTP_RESPONSE_OK; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->ResponseLength = MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->RECEIVE_DATA_STATUS = RECEIVE_IDLE_STATE; } else { hmtp->RECEIVE_DATA_STATUS = RECEIVE_REST_OF_DATA; } tmp = (uint32_t)buff; hmtpif->WriteData(len, (uint8_t *)(tmp + 12U)); break; case RECEIVE_REST_OF_DATA: hmtpif->WriteData(len, buff); break; case SEND_RESPONSE: hmtpif->WriteData(0, buff); /* send 0 length to stop write process */ hmtp->GenericContainer.code = MTP_RESPONSE_OK; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->ResponseLength = MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->RECEIVE_DATA_STATUS = RECEIVE_IDLE_STATE; break; default: break; } hmtp->ResponseCode = MTP_RESPONSE_OK; } /** * @brief USBD_MTP_OPT_SendObjectInfo * Send the object information from host to MTP device * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_SendObjectInfo(USBD_HandleTypeDef *pdev, uint8_t *buff, uint32_t len) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; MTP_ObjectInfoTypeDef ObjectInfo; uint8_t dataLength = offsetof(MTP_ObjectInfoTypeDef, Filename); uint8_t *tmp; switch (hmtp->RECEIVE_DATA_STATUS) { case RECEIVE_IDLE_STATE: hmtp->RECEIVE_DATA_STATUS = RECEIVE_COMMAND_DATA; break; case RECEIVE_COMMAND_DATA: /* store object handle and storage id for future use */ if (hmtp->OperationsContainer.Param2 == 0xFFFFFFFFU) { objhandle = 0U; } else { objhandle = hmtp->OperationsContainer.Param2; } storage_id = hmtp->OperationsContainer.Param1; hmtp->RECEIVE_DATA_STATUS = RECEIVE_FIRST_DATA; break; case RECEIVE_FIRST_DATA: tmp = buff; (void)USBD_memcpy(ObjInfo_buff, tmp + 12U, (uint16_t)(hmtp->MaxPcktLen - MTP_CONT_HEADER_SIZE)); hmtp->RECEIVE_DATA_STATUS = RECEIVE_REST_OF_DATA; break; case RECEIVE_REST_OF_DATA: (void)USBD_memcpy(ObjInfo_buff + len, buff, hmtp->MaxPcktLen); break; case SEND_RESPONSE: (void)USBD_memcpy((uint8_t *)&ObjectInfo, ObjInfo_buff, dataLength); (void)USBD_memcpy((uint8_t *)&ObjectInfo.Filename, (ObjInfo_buff + dataLength), ((uint32_t)(ObjectInfo.Filename_len) * 2U)); obj_format = ObjectInfo.ObjectFormat; hmtp->ResponseCode = hmtpif->Create_NewObject(ObjectInfo, objhandle); hmtp->GenericContainer.code = (uint16_t)hmtp->ResponseCode; hmtp->ResponseLength = MTP_CONT_HEADER_SIZE + (sizeof(uint32_t) * 3U); /* Header + 3 Param */ hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; (void)MTP_Get_PayloadContent(pdev); hmtp->RECEIVE_DATA_STATUS = RECEIVE_IDLE_STATE; break; default: break; } } /** * @brief USBD_MTP_OPT_DeleteObject * Delete the object from the device * @param pdev: device instance * @retval None */ void USBD_MTP_OPT_DeleteObject(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; hmtp->GenericContainer.trans_id = hmtp->OperationsContainer.trans_id; hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE; hmtp->ResponseLength = MTP_CONT_HEADER_SIZE; hmtp->GenericContainer.length = hmtp->ResponseLength; hmtp->ResponseCode = hmtpif->DeleteObject(hmtp->OperationsContainer.Param1); } /** * @brief MTP_Get_PayloadContent * Get the payload data of generic container * @param pdev: device instance * @retval None */ static void MTP_Get_PayloadContent(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; uint8_t *buffer; uint32_t n_idx; switch (hmtp->OperationsContainer.code) { case MTP_OP_GET_DEVICE_INFO: (void)MTP_Get_DeviceInfo(); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_DeviceInfo, MIN(sizeof(MTP_DeviceInfo), MTP_MEDIA_PACKET)); break; case MTP_OP_GET_STORAGE_IDS: (void)MTP_Get_StorageIDS(); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_StorageIDS, sizeof(MTP_StorageIDS)); break; case MTP_OP_GET_STORAGE_INFO: (void)MTP_Get_StorageInfo(pdev); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_StorageInfo, sizeof(MTP_StorageInfo)); break; case MTP_OP_GET_OBJECT_HANDLES: (void)MTP_Get_ObjectHandle(pdev); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_ObjectHandle, hmtp->ResponseLength); break; case MTP_OP_GET_OBJECT_INFO: (void)MTP_Get_ObjectInfo(pdev); break; case MTP_OP_GET_OBJECT_PROPS_SUPPORTED: (void)MTP_Get_ObjectPropSupp(); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_ObjectPropSupp, sizeof(MTP_ObjectPropSupp)); break; case MTP_OP_GET_OBJECT_PROP_DESC: (void)MTP_Get_ObjectPropDesc(pdev); hmtp->ResponseLength = MTP_build_data_propdesc(pdev, MTP_ObjectPropDesc); break; case MTP_OP_GET_OBJECT_PROP_REFERENCES: MTP_Ref.ref_len = 0U; (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_Ref.ref_len, sizeof(MTP_Ref.ref_len)); break; case MTP_OP_GET_OBJECT_PROPLIST: (void)MTP_Get_ObjectPropList(pdev); break; case MTP_OP_GET_OBJECT_PROP_VALUE: buffer = MTP_Get_ObjectPropValue(pdev); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)buffer, hmtp->ResponseLength); break; case MTP_OP_GET_DEVICE_PROP_DESC: (void)MTP_Get_DevicePropDesc(); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_DevicePropDesc, MIN(sizeof(MTP_DevicePropDesc), MTP_MEDIA_PACKET)); break; case MTP_OP_SEND_OBJECT_INFO: n_idx = hmtpif->GetNewIndex(obj_format); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&storage_id, sizeof(uint32_t)); (void)USBD_memcpy(hmtp->GenericContainer.data + 4U, (const uint8_t *)&objhandle, sizeof(uint32_t)); (void)USBD_memcpy(hmtp->GenericContainer.data + 8U, (const uint8_t *)&n_idx, sizeof(uint32_t)); break; case MTP_OP_GET_OBJECT: break; default: break; } } /** * @brief MTP_Get_DeviceInfo * Fill the MTP_DeviceInfo struct * @param pdev: device instance * @retval None */ static void MTP_Get_DeviceInfo(void) { MTP_DeviceInfo.StandardVersion = STANDARD_VERSION; MTP_DeviceInfo.VendorExtensionID = VEND_EXT_ID; MTP_DeviceInfo.VendorExtensionVersion = VEND_EXT_VERSION; MTP_DeviceInfo.VendorExtensionDesc_len = (uint8_t)VEND_EXT_DESC_LEN; uint32_t i; #if USBD_MTP_VEND_EXT_DESC_SUPPORTED == 1 for (i = 0U; i < VEND_EXT_DESC_LEN; i++) { MTP_DeviceInfo.VendorExtensionDesc[i] = VendExtDesc[i]; } #endif /* USBD_MTP_VEND_EXT_DESC_SUPPORTED */ MTP_DeviceInfo.FunctionalMode = FUNCTIONAL_MODE; /* device supports one mode , standard mode */ /* All supported operation */ MTP_DeviceInfo.OperationsSupported_len = SUPP_OP_LEN; for (i = 0U; i < SUPP_OP_LEN; i++) { MTP_DeviceInfo.OperationsSupported[i] = SuppOP[i]; } MTP_DeviceInfo.EventsSupported_len = SUPP_EVENTS_LEN; /* event that are currently generated by the device*/ #if USBD_MTP_EVENTS_SUPPORTED == 1 for (i = 0U; i < SUPP_EVENTS_LEN; i++) { MTP_DeviceInfo.EventsSupported[i] = SuppEvents[i]; } #endif /* USBD_MTP_EVENTS_SUPPORTED */ MTP_DeviceInfo.DevicePropertiesSupported_len = SUPP_DEVICE_PROP_LEN; #if USBD_MTP_DEVICE_PROP_SUPPORTED == 1 for (i = 0U; i < SUPP_DEVICE_PROP_LEN; i++) { MTP_DeviceInfo.DevicePropertiesSupported[i] = DevicePropSupp[i]; } #endif /* USBD_MTP_DEVICE_PROP_SUPPORTED */ MTP_DeviceInfo.CaptureFormats_len = SUPP_CAPT_FORMAT_LEN; #if USBD_MTP_CAPTURE_FORMAT_SUPPORTED == 1 for (i = 0U; i < SUPP_CAPT_FORMAT_LEN; i++) { MTP_DeviceInfo.CaptureFormats[i] = SuppCaptFormat[i]; } #endif /* USBD_MTP_CAPTURE_FORMAT_SUPPORTED */ MTP_DeviceInfo.ImageFormats_len = SUPP_IMG_FORMAT_LEN; /* number of image formats that are supported by the device*/ for (i = 0U; i < SUPP_IMG_FORMAT_LEN; i++) { MTP_DeviceInfo.ImageFormats[i] = SuppImgFormat[i]; } MTP_DeviceInfo.Manufacturer_len = (uint8_t)MANUF_LEN; for (i = 0U; i < MANUF_LEN; i++) { MTP_DeviceInfo.Manufacturer[i] = Manuf[i]; } MTP_DeviceInfo.Model_len = (uint8_t)MODEL_LEN; for (i = 0U; i < MODEL_LEN; i++) { MTP_DeviceInfo.Model[i] = Model[i]; } MTP_DeviceInfo.DeviceVersion_len = (uint8_t)DEVICE_VERSION_LEN; for (i = 0U; i < DEVICE_VERSION_LEN; i++) { MTP_DeviceInfo.DeviceVersion[i] = DeviceVers[i]; } MTP_DeviceInfo.SerialNumber_len = (uint8_t)SERIAL_NBR_LEN; for (i = 0U; i < SERIAL_NBR_LEN; i++) { MTP_DeviceInfo.SerialNumber[i] = SerialNbr[i]; } } /** * @brief MTP_Get_StorageInfo * Fill the MTP_StorageInfo struct * @param pdev: device instance * @retval None */ static void MTP_Get_StorageInfo(USBD_HandleTypeDef *pdev) { USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; MTP_StorageInfo.StorageType = MTP_STORAGE_REMOVABLE_RAM; MTP_StorageInfo.FilesystemType = MTP_FILESYSTEM_GENERIC_FLAT; MTP_StorageInfo.AccessCapability = MTP_ACCESS_CAP_RW; MTP_StorageInfo.MaxCapability = hmtpif->GetMaxCapability(); MTP_StorageInfo.FreeSpaceInBytes = hmtpif->GetFreeSpaceInBytes(); MTP_StorageInfo.FreeSpaceInObjects = FREE_SPACE_IN_OBJ_NOT_USED; /* not used */ MTP_StorageInfo.StorageDescription = 0U; MTP_StorageInfo.VolumeLabel = 0U; } /** * @brief MTP_Get_ObjectHandle * Fill the MTP_ObjectHandle struct * @param pdev: device instance * @retval None */ static void MTP_Get_ObjectHandle(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; MTP_ObjectHandle.ObjectHandle_len = (uint32_t)(hmtpif->GetIdx(hmtp->OperationsContainer.Param3, MTP_ObjectHandle.ObjectHandle)); hmtp->ResponseLength = (MTP_ObjectHandle.ObjectHandle_len * sizeof(uint32_t)) + sizeof(uint32_t); } /** * @brief MTP_Get_ObjectPropSupp * Fill the MTP_ObjectPropSupp struct * @param pdev: device instance * @retval None */ static void MTP_Get_ObjectPropSupp(void) { uint32_t i; MTP_ObjectPropSupp.ObjectPropSupp_len = SUPP_OBJ_PROP_LEN; for (i = 0U; i < SUPP_OBJ_PROP_LEN; i++) { MTP_ObjectPropSupp.ObjectPropSupp[i] = ObjectPropSupp[i]; } } /** * @brief MTP_Get_ObjectPropDesc * Fill the MTP_ObjectPropDesc struct * @param pdev: device instance * @retval None */ static void MTP_Get_ObjectPropDesc(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint16_t undef_format = MTP_OBJ_FORMAT_UNDEFINED; uint32_t storageid = MTP_STORAGE_ID; switch (hmtp->OperationsContainer.Param1) /* switch obj prop code */ { case MTP_OB_PROP_OBJECT_FORMAT : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT16; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_ObjectPropDesc.DefValue = (uint8_t *)&undef_format; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_STORAGE_ID : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT32; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_ObjectPropDesc.DefValue = (uint8_t *)&storageid; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_OBJ_FILE_NAME : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_STR; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_FileName.FileName_len = DEFAULT_FILE_NAME_LEN; (void)USBD_memcpy((void *) & (MTP_FileName.FileName), (const void *)DefaultFileName, sizeof(DefaultFileName)); MTP_ObjectPropDesc.DefValue = (uint8_t *)&MTP_FileName; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_PARENT_OBJECT : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT32; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_ObjectPropDesc.DefValue = 0U; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_OBJECT_SIZE : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT64; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_ObjectPropDesc.DefValue = 0U; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_NAME : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_STR; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_FileName.FileName_len = DEFAULT_FILE_NAME_LEN; (void)USBD_memcpy((void *) & (MTP_FileName.FileName), (const void *)DefaultFileName, sizeof(DefaultFileName)); MTP_ObjectPropDesc.DefValue = (uint8_t *)&MTP_FileName; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT128; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET; MTP_ObjectPropDesc.DefValue = 0U; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; case MTP_OB_PROP_PROTECTION_STATUS : MTP_ObjectPropDesc.ObjectPropertyCode = (uint16_t)(hmtp->OperationsContainer.Param1); MTP_ObjectPropDesc.DataType = MTP_DATATYPE_UINT16; MTP_ObjectPropDesc.GetSet = MTP_PROP_GET_SET; MTP_ObjectPropDesc.DefValue = 0U; MTP_ObjectPropDesc.GroupCode = 0U; MTP_ObjectPropDesc.FormFlag = 0U; break; default: break; } } /** * @brief MTP_Get_ObjectPropValue * Get the property value * @param pdev: device instance * @retval None */ static uint8_t *MTP_Get_ObjectPropValue(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; static uint8_t buf[512]; /* Add all other supported object properties */ switch (hmtp->OperationsContainer.Param2) { case MTP_OB_PROP_STORAGE_ID: MTP_PropertyValue.u32 = MTP_STORAGE_ID; (void)USBD_memcpy(buf, (const uint8_t *)&MTP_PropertyValue, sizeof(uint32_t)); hmtp->ResponseLength = sizeof(uint32_t); break; case MTP_OB_PROP_OBJECT_FORMAT: MTP_PropertyValue.u16 = hmtpif->GetObjectFormat(hmtp->OperationsContainer.Param1); (void)USBD_memcpy(buf, (const uint8_t *)&MTP_PropertyValue, sizeof(uint16_t)); hmtp->ResponseLength = sizeof(uint16_t); break; case MTP_OB_PROP_OBJ_FILE_NAME: MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, (uint16_t *)buf); (void)USBD_memcpy(MTP_FileName.FileName, (uint16_t *)buf, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); hmtp->ResponseLength = ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U; break; case MTP_OB_PROP_PARENT_OBJECT : MTP_PropertyValue.u32 = hmtpif->GetParentObject(hmtp->OperationsContainer.Param1); (void)USBD_memcpy(buf, (const uint8_t *)&MTP_PropertyValue, sizeof(uint32_t)); hmtp->ResponseLength = sizeof(uint32_t); break; case MTP_OB_PROP_OBJECT_SIZE : MTP_PropertyValue.u64 = hmtpif->GetObjectSize(hmtp->OperationsContainer.Param1); (void)USBD_memcpy(buf, (const uint8_t *)&MTP_PropertyValue, sizeof(uint64_t)); hmtp->ResponseLength = sizeof(uint64_t); break; default: break; } return buf; } /** * @brief MTP_Get_ObjectPropList * Get the object property list data to be transmitted * @param pdev: device instance * @retval None */ static void MTP_Get_ObjectPropList(USBD_HandleTypeDef *pdev) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; uint16_t filename[255]; uint32_t storageid = MTP_STORAGE_ID; uint32_t default_val = 0U; uint32_t i; uint16_t format; uint64_t objsize; uint32_t parent_proval; uint8_t mtp_pers_uniq_obj_id[16] = {0}; MTP_PropertiesList.MTP_Properties_len = SUPP_OBJ_PROP_LEN; hmtp->ResponseLength = 4U; /* size of MTP_PropertiesList.MTP_Properties_len */ (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_PropertiesList.MTP_Properties_len, hmtp->ResponseLength); for (i = 0U; i < SUPP_OBJ_PROP_LEN; i++) { MTP_PropertiesList.MTP_Properties[i].ObjectHandle = hmtp->OperationsContainer.Param1; switch (ObjectPropSupp[i]) { case MTP_OB_PROP_STORAGE_ID : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_STORAGE_ID; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT32; MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&storageid; break; case MTP_OB_PROP_OBJECT_FORMAT : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_FORMAT; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT16; format = hmtpif->GetObjectFormat(hmtp->OperationsContainer.Param1); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&format; break; case MTP_OB_PROP_OBJ_FILE_NAME: MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_OBJ_FILE_NAME; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_STR; /* MTP_FileName.FileName_len value shall be set before USBD_MTP_FS_GetObjectName */ MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, filename); (void)USBD_memcpy(MTP_FileName.FileName, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&MTP_FileName; break; case MTP_OB_PROP_PARENT_OBJECT : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_PARENT_OBJECT; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT32; parent_proval = hmtpif->GetParentObject(hmtp->OperationsContainer.Param1); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&parent_proval; break; case MTP_OB_PROP_OBJECT_SIZE : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_SIZE; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT64; objsize = hmtpif->GetObjectSize(hmtp->OperationsContainer.Param1); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&objsize; break; case MTP_OB_PROP_NAME : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_NAME; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_STR; /* MTP_FileName.FileName_len value shall be set before USBD_MTP_FS_GetObjectName */ MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, filename); (void)USBD_memcpy(MTP_FileName.FileName, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&MTP_FileName; break; case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN : /* Fill in the first 4 bytes with Param1 (Object ID) */ (void)USBD_memcpy(mtp_pers_uniq_obj_id, &hmtp->OperationsContainer.Param1, sizeof(hmtp->OperationsContainer.Param1)); MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT128; MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)mtp_pers_uniq_obj_id; break; case MTP_OB_PROP_PROTECTION_STATUS : MTP_PropertiesList.MTP_Properties[i].PropertyCode = MTP_OB_PROP_PROTECTION_STATUS; MTP_PropertiesList.MTP_Properties[i].Datatype = MTP_DATATYPE_UINT16; MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&default_val; break; default: break; } hmtp->ResponseLength = MTP_build_data_proplist(pdev, MTP_PropertiesList, i); } } /** * @brief MTP_Get_DevicePropDesc * Fill the MTP_DevicePropDesc struct * @param pdev: device instance * @retval None */ static void MTP_Get_DevicePropDesc(void) { MTP_DevicePropDesc.DevicePropertyCode = MTP_DEV_PROP_DEVICE_FRIENDLY_NAME; MTP_DevicePropDesc.DataType = MTP_DATATYPE_STR; MTP_DevicePropDesc.GetSet = MTP_PROP_GET_SET; MTP_DevicePropDesc.DefValue_len = DEVICE_PROP_DESC_DEF_LEN; uint32_t i; for (i = 0U; i < (sizeof(DevicePropDefVal) / 2U); i++) { MTP_DevicePropDesc.DefValue[i] = DevicePropDefVal[i]; } MTP_DevicePropDesc.curDefValue_len = DEVICE_PROP_DESC_CUR_LEN; for (i = 0U; i < (sizeof(DevicePropCurDefVal) / 2U); i++) { MTP_DevicePropDesc.curDefValue[i] = DevicePropCurDefVal[i]; } MTP_DevicePropDesc.FormFlag = 0U; } /** * @brief MTP_Get_ObjectInfo * Fill the MTP_ObjectInfo struct * @param pdev: device instance * @retval None */ static void MTP_Get_ObjectInfo(USBD_HandleTypeDef *pdev) { USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint16_t filename[255]; MTP_ObjectInfo.Storage_id = MTP_STORAGE_ID; MTP_ObjectInfo.ObjectFormat = hmtpif->GetObjectFormat(hmtp->OperationsContainer.Param1); MTP_ObjectInfo.ObjectCompressedSize = hmtpif->GetObjectSize(hmtp->OperationsContainer.Param1); MTP_ObjectInfo.ProtectionStatus = 0U; MTP_ObjectInfo.ThumbFormat = MTP_OBJ_FORMAT_UNDEFINED; MTP_ObjectInfo.ThumbCompressedSize = 0U; MTP_ObjectInfo.ThumbPixWidth = 0U; /* not supported or not an image */ MTP_ObjectInfo.ThumbPixHeight = 0U; MTP_ObjectInfo.ImagePixWidth = 0U; MTP_ObjectInfo.ImagePixHeight = 0U; MTP_ObjectInfo.ImageBitDepth = 0U; MTP_ObjectInfo.ParentObject = hmtpif->GetParentObject(hmtp->OperationsContainer.Param1); MTP_ObjectInfo.AssociationType = 0U; MTP_ObjectInfo.AssociationDesc = 0U; MTP_ObjectInfo.SequenceNumber = 0U; /* we have to get this value before MTP_ObjectInfo.Filename */ MTP_ObjectInfo.Filename_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_ObjectInfo.Filename_len, filename); (void)USBD_memcpy(MTP_ObjectInfo.Filename, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); MTP_ObjectInfo.CaptureDate = 0U; MTP_ObjectInfo.ModificationDate = 0U; MTP_ObjectInfo.Keywords = 0U; hmtp->ResponseLength = MTP_build_data_ObjInfo(pdev, MTP_ObjectInfo); } /** * @brief MTP_Get_StorageIDS * Fill the MTP_StorageIDS struct * @param pdev: device instance * @retval None */ static void MTP_Get_StorageIDS(void) { MTP_StorageIDS.StorageIDS_len = MTP_NBR_STORAGE_ID; MTP_StorageIDS.StorageIDS[0] = MTP_STORAGE_ID; } /** * @brief MTP_build_data_propdesc * Copy the MTP_ObjectPropDesc dataset to the payload data * @param pdev: device instance * @retval None */ static uint32_t MTP_build_data_propdesc(USBD_HandleTypeDef *pdev, MTP_ObjectPropDescTypeDef def) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint8_t DefValue_size = (MTP_FileName.FileName_len * 2U) + 1U; uint32_t dataLength = offsetof(MTP_ObjectPropDescTypeDef, DefValue); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&def, dataLength); switch (def.DataType) { case MTP_DATATYPE_UINT16: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint16_t)); dataLength += sizeof(uint16_t); break; case MTP_DATATYPE_UINT32: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint32_t)); dataLength += sizeof(uint32_t); break; case MTP_DATATYPE_UINT64: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint64_t)); dataLength += sizeof(uint64_t); break; case MTP_DATATYPE_STR: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, DefValue_size); dataLength += DefValue_size; break; case MTP_DATATYPE_UINT128: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, (sizeof(uint64_t) * 2U)); dataLength += (sizeof(uint64_t) * 2U); break; default: break; } (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, (const uint8_t *)&MTP_ObjectPropDesc.GroupCode, sizeof(MTP_ObjectPropDesc.GroupCode)); dataLength += sizeof(MTP_ObjectPropDesc.GroupCode); (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, (const uint8_t *)&MTP_ObjectPropDesc.FormFlag, sizeof(MTP_ObjectPropDesc.FormFlag)); dataLength += sizeof(MTP_ObjectPropDesc.FormFlag); return dataLength; } /** * @brief MTP_build_data_proplist * Copy the MTP_PropertiesList dataset to the payload data * @param pdev: device instance * @retval None */ static uint32_t MTP_build_data_proplist(USBD_HandleTypeDef *pdev, MTP_PropertiesListTypedef proplist, uint32_t idx) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint8_t *propval = proplist.MTP_Properties[idx].propval; uint8_t propval_size = (propval[0] * 2U) + 1U; uint32_t dataLength; dataLength = offsetof(MTP_PropertiesTypedef, propval); (void)USBD_memcpy(hmtp->GenericContainer.data + hmtp->ResponseLength, (const uint8_t *)&proplist.MTP_Properties[idx], dataLength); dataLength += hmtp->ResponseLength; switch (proplist.MTP_Properties[idx].Datatype) { case MTP_DATATYPE_UINT16: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, proplist.MTP_Properties[idx].propval, sizeof(uint16_t)); dataLength += sizeof(uint16_t); break; case MTP_DATATYPE_UINT32: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, proplist.MTP_Properties[idx].propval, sizeof(uint32_t)); dataLength += sizeof(uint32_t); break; case MTP_DATATYPE_STR: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, proplist.MTP_Properties[idx].propval, propval_size); dataLength += propval_size; break; case MTP_DATATYPE_UINT64: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, proplist.MTP_Properties[idx].propval, sizeof(uint64_t)); dataLength += sizeof(uint64_t); break; case MTP_DATATYPE_UINT128: (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, proplist.MTP_Properties[idx].propval, (sizeof(uint64_t) * 2U)); dataLength += (sizeof(uint64_t) * 2U); break; default: break; } return dataLength; } /** * @brief MTP_build_data_ObjInfo * Copy the MTP_ObjectInfo dataset to the payload data * @param pdev: device instance * @retval None */ static uint32_t MTP_build_data_ObjInfo(USBD_HandleTypeDef *pdev, MTP_ObjectInfoTypeDef objinfo) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint32_t ObjInfo_len = offsetof(MTP_ObjectInfoTypeDef, Filename); (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&objinfo, ObjInfo_len); (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, (const uint8_t *)&objinfo.Filename, objinfo.Filename_len * sizeof(uint16_t)); ObjInfo_len = ObjInfo_len + (objinfo.Filename_len * sizeof(uint16_t)); (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, (const uint8_t *)&objinfo.CaptureDate, sizeof(objinfo.CaptureDate)); ObjInfo_len = ObjInfo_len + sizeof(objinfo.CaptureDate); return ObjInfo_len; }