/** ****************************************************************************** * @file usbh_mtp.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the MTP Layer Handlers for USB Host MTP class. * * @verbatim * * =================================================================== * MTP Class Description * =================================================================== * This module manages the MSC class V1.11 following the "Device Class Definition * for Human Interface Devices (MTP) Version 1.11 Jun 27, 2001". * This driver implements the following aspects of the specification: * - The Boot Interface Subclass * - The Mouse and Keyboard protocols * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_mtp.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MTP_CLASS * @{ */ /** @defgroup USBH_MTP_CORE * @brief This file includes MTP Layer Handlers for USB Host MTP class. * @{ */ /** @defgroup USBH_MTP_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost); static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost); static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost); static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost); static void MTP_DecodeEvent (USBH_HandleTypeDef *phost) ; USBH_ClassTypeDef MTP_Class = { "MTP", USB_MTP_CLASS, USBH_MTP_InterfaceInit, USBH_MTP_InterfaceDeInit, USBH_MTP_ClassRequest, USBH_MTP_Process, USBH_MTP_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Functions * @{ */ /** * @brief USBH_MTP_InterfaceInit * The function init the MTP class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK ; uint8_t interface, endpoint; MTP_HandleTypeDef *MTP_Handle; interface = USBH_FindInterface(phost, USB_MTP_CLASS, 1, 1); if(interface == 0xFF) /* No Valid Interface */ { status = USBH_FAIL; USBH_DbgLog ("Cannot Find the interface for Still Image Class."); } else { USBH_SelectInterface (phost, interface); endpoint = MTP_FindCtlEndpoint(phost); phost->pActiveClass->pData = (MTP_HandleTypeDef *)USBH_malloc (sizeof(MTP_HandleTypeDef)); MTP_Handle = phost->pActiveClass->pData; if( MTP_Handle == NULL) { status = USBH_FAIL; USBH_DbgLog ("Cannot allocate RAM for MTP Handle"); } /*Collect the control endpoint address and length*/ MTP_Handle->NotificationEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->NotificationEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->NotificationPipe = USBH_AllocPipe(phost, MTP_Handle->NotificationEp); MTP_Handle->events.poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bInterval; /* Open pipe for Notification endpoint */ USBH_OpenPipe (phost, MTP_Handle->NotificationPipe, MTP_Handle->NotificationEp, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, MTP_Handle->NotificationEpSize); USBH_LL_SetToggle (phost, MTP_Handle->NotificationPipe, 0); endpoint = MTP_FindDataInEndpoint(phost); /*Collect the control endpoint address and length*/ MTP_Handle->DataInEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->DataInEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->DataInPipe = USBH_AllocPipe(phost, MTP_Handle->DataInEp); /* Open pipe for DATA IN endpoint */ USBH_OpenPipe (phost, MTP_Handle->DataInPipe, MTP_Handle->DataInEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MTP_Handle->DataInEpSize); USBH_LL_SetToggle (phost, MTP_Handle->DataInPipe, 0); endpoint = MTP_FindDataOutEndpoint(phost); /*Collect the DATA OUT endpoint address and length*/ MTP_Handle->DataOutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->DataOutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->DataOutPipe = USBH_AllocPipe(phost, MTP_Handle->DataOutEp); /* Open pipe for DATA OUT endpoint */ USBH_OpenPipe (phost, MTP_Handle->DataOutPipe, MTP_Handle->DataOutEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MTP_Handle->DataOutEpSize); USBH_LL_SetToggle (phost, MTP_Handle->DataOutPipe, 0); MTP_Handle->state = MTP_OPENSESSION; MTP_Handle->is_ready = 0; MTP_Handle->events.state = MTP_EVENTS_INIT; return USBH_PTP_Init(phost); } return status; } /** * @brief Find MTP Ctl interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_INTERRUPT) == USBH_EP_INTERRUPT)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief Find MTP DATA OUT interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if(((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80) == 0)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief Find MTP DATA IN interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief USBH_MTP_InterfaceDeInit * The function DeInit the Pipes used for the MTP class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if (MTP_Handle->DataOutPipe) { USBH_ClosePipe(phost, MTP_Handle->DataOutPipe); USBH_FreePipe (phost, MTP_Handle->DataOutPipe); MTP_Handle->DataOutPipe = 0; /* Reset the Channel as Free */ } if (MTP_Handle->DataInPipe) { USBH_ClosePipe(phost, MTP_Handle->DataInPipe); USBH_FreePipe (phost, MTP_Handle->DataInPipe); MTP_Handle->DataInPipe = 0; /* Reset the Channel as Free */ } if (MTP_Handle->NotificationPipe) { USBH_ClosePipe(phost, MTP_Handle->NotificationPipe); USBH_FreePipe (phost, MTP_Handle->NotificationPipe); MTP_Handle->NotificationPipe = 0; /* Reset the Channel as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } return USBH_OK; } /** * @brief USBH_MTP_ClassRequest * The function is responsible for handling Standard requests * for MTP class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost) { return USBH_OK;; } /** * @brief USBH_MTP_Process * The function is for managing state machine for MTP data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t idx = 0; switch(MTP_Handle->state) { case MTP_OPENSESSION: status = USBH_PTP_OpenSession (phost, 1); /* Session '0' is not valid */ if(status == USBH_OK) { USBH_UsrLog("MTP Session #0 Opened"); MTP_Handle->state = MTP_GETDEVICEINFO; } break; case MTP_GETDEVICEINFO: status = USBH_PTP_GetDeviceInfo (phost, &(MTP_Handle->info.devinfo)); if(status == USBH_OK) { USBH_DbgLog(">>>>> MTP Device Information"); USBH_DbgLog("Standard version : %x", MTP_Handle->info.devinfo.StandardVersion); USBH_DbgLog("Vendor ExtID : %s", (MTP_Handle->info.devinfo.VendorExtensionID == 6)?"MTP": "NOT SUPPORTED"); USBH_DbgLog("Functional mode : %s", (MTP_Handle->info.devinfo.FunctionalMode == 0) ? "Standard" : "Vendor"); USBH_DbgLog("Number of Supported Operation(s) : %d", MTP_Handle->info.devinfo.OperationsSupported_len); USBH_DbgLog("Number of Supported Events(s) : %d", MTP_Handle->info.devinfo.EventsSupported_len); USBH_DbgLog("Number of Supported Proprieties : %d", MTP_Handle->info.devinfo.DevicePropertiesSupported_len); USBH_DbgLog("Manufacturer : %s", MTP_Handle->info.devinfo.Manufacturer); USBH_DbgLog("Model : %s", MTP_Handle->info.devinfo.Model); USBH_DbgLog("Device version : %s", MTP_Handle->info.devinfo.DeviceVersion); USBH_DbgLog("Serial number : %s", MTP_Handle->info.devinfo.SerialNumber); MTP_Handle->state = MTP_GETSTORAGEIDS; } break; case MTP_GETSTORAGEIDS: status = USBH_PTP_GetStorageIds (phost, &(MTP_Handle->info.storids)); if(status == USBH_OK) { USBH_DbgLog("Number of storage ID items : %d", MTP_Handle->info.storids.n); for (idx = 0; idx < MTP_Handle->info.storids.n; idx ++) { USBH_DbgLog("storage#%d ID : %x", idx, MTP_Handle->info.storids.Storage[idx]); } MTP_Handle->current_storage_unit = 0; MTP_Handle->state = MTP_GETSTORAGEINFO; } break; case MTP_GETSTORAGEINFO: status = USBH_PTP_GetStorageInfo (phost, MTP_Handle->info.storids.Storage[MTP_Handle->current_storage_unit], &((MTP_Handle->info.storinfo)[MTP_Handle->current_storage_unit])); if(status == USBH_OK) { USBH_UsrLog("Volume#%lu: %s [%s]", MTP_Handle->current_storage_unit, MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].StorageDescription, MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].VolumeLabel); if(++MTP_Handle->current_storage_unit >= MTP_Handle->info.storids.n) { MTP_Handle->state = MTP_IDLE; MTP_Handle->is_ready = 1; MTP_Handle->current_storage_unit = 0; MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[0]; USBH_UsrLog( "MTP Class initialized."); USBH_UsrLog("%s is default storage unit", MTP_Handle->info.storinfo[0].StorageDescription); phost->pUser(phost, HOST_USER_CLASS_ACTIVE); } } break; case MTP_IDLE: USBH_MTP_Events(phost); default: status = USBH_OK; break; } return status; } /** * @brief USBH_MTP_SOFProcess * The function is for managing SOF callback * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; return status; } /** * @brief USBH_MTP_IsReady * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ uint8_t USBH_MTP_IsReady (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; return (MTP_Handle->is_ready); } /** * @brief USBH_MTP_GetNumStorage * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetNumStorage (USBH_HandleTypeDef *phost, uint8_t *storage_num) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if(MTP_Handle->is_ready > 0) { *storage_num = MTP_Handle->info.storids.n; status = USBH_OK; } return status; } /** * @brief USBH_MTP_SelectStorage * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_SelectStorage (USBH_HandleTypeDef *phost, uint8_t storage_idx) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[storage_idx]; status = USBH_OK; } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint8_t storage_idx, MTP_StorageInfoTypedef *info) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { *info = MTP_Handle->info.storinfo[storage_idx]; status = USBH_OK; } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetNumObjects (USBH_HandleTypeDef *phost, uint32_t storage_idx, uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { while ((status = USBH_PTP_GetNumObjects (phost, MTP_Handle->info.storids.Storage[storage_idx], objectformatcode, associationOH, numobs)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectHandles (USBH_HandleTypeDef *phost, uint32_t storage_idx, uint32_t objectformatcode, uint32_t associationOH, PTP_ObjectHandlesTypedef* objecthandles) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { while ((status = USBH_PTP_GetObjectHandles (phost, MTP_Handle->info.storids.Storage[storage_idx], objectformatcode, associationOH, objecthandles)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_PTP_GetObjectInfo * Gets objert info * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectInfo (USBH_HandleTypeDef *phost, uint32_t handle, PTP_ObjectInfoTypedef* objectinfo) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectInfo (phost, handle, objectinfo)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_DeleteObject * Delete an object. * @param phost: Host handle * @param handle : Object Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_DeleteObject (USBH_HandleTypeDef *phost, uint32_t handle, uint32_t objectformatcode) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_DeleteObject (phost, handle, objectformatcode)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObject * Gets object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObject (phost, handle, object)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetPartialObject * Gets object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetPartialObject(USBH_HandleTypeDef *phost, uint32_t handle, uint32_t offset, uint32_t maxbytes, uint8_t *object, uint32_t *len) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetPartialObject(phost, handle, offset, maxbytes, object, len)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropsSupported * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost, uint16_t ofc, uint32_t *propnum, uint16_t *props) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropsSupported (phost, ofc, propnum, props)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, uint16_t opc, uint16_t ofc, PTP_ObjectPropDescTypeDef *opd) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropDesc (phost, opc, ofc, opd)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropList * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropList (USBH_HandleTypeDef *phost, uint32_t handle, MTP_PropertiesTypedef *pprops, uint32_t *nrofprops) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropList (phost, handle, pprops, nrofprops)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_SendObject * Send an object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_SendObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object, uint32_t size) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_SendObject (phost, handle, object, size)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief Handle HID Control process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; switch(MTP_Handle->events.state) { case MTP_EVENTS_INIT: if((phost->Timer & 1) == 0) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); MTP_Handle->events.state = MTP_EVENTS_GETDATA ; } break; case MTP_EVENTS_GETDATA: if(USBH_LL_GetURBState(phost , MTP_Handle->NotificationPipe) == USBH_URB_DONE) { MTP_DecodeEvent(phost); } if(( phost->Timer - MTP_Handle->events.timer) >= MTP_Handle->events.poll) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); } break; default: break; } return status; } /** * @brief MTP_DecodeEvent * Decode device event sent by responder * @param phost: Host handle * @retval None */ static void MTP_DecodeEvent (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint16_t code; uint32_t param1; /* Process the event */ code = MTP_Handle->events.container.code; param1 = MTP_Handle->events.container.param1; switch(code) { case PTP_EC_Undefined: USBH_DbgLog("EVT: PTP_EC_Undefined in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_CancelTransaction: USBH_DbgLog("EVT: PTP_EC_CancelTransaction in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectAdded: USBH_DbgLog("EVT: PTP_EC_ObjectAdded in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectRemoved: USBH_DbgLog("EVT: PTP_EC_ObjectRemoved in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreAdded: USBH_DbgLog("EVT: PTP_EC_StoreAdded in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreRemoved: USBH_DbgLog("EVT: PTP_EC_StoreRemoved in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DevicePropChanged: USBH_DbgLog("EVT: PTP_EC_DevicePropChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectInfoChanged: USBH_DbgLog("EVT: PTP_EC_ObjectInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DeviceInfoChanged: USBH_DbgLog("EVT: PTP_EC_DeviceInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_RequestObjectTransfer: USBH_DbgLog("EVT: PTP_EC_RequestObjectTransfer in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreFull: USBH_DbgLog("EVT: PTP_EC_StoreFull in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DeviceReset: USBH_DbgLog("EVT: PTP_EC_DeviceReset in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StorageInfoChanged : USBH_DbgLog( "EVT: PTP_EC_StorageInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_CaptureComplete : USBH_DbgLog( "EVT: PTP_EC_CaptureComplete in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_UnreportedStatus : USBH_DbgLog( "EVT: PTP_EC_UnreportedStatus in session %u", MTP_Handle->ptp.session_id); break; default : USBH_DbgLog( "Received unknown event in session %u", MTP_Handle->ptp.session_id); break; } USBH_MTP_EventsCallback(phost, code, param1); } /** * @brief USBH_MTP_GetDevicePropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetDevicePropDesc (USBH_HandleTypeDef *phost, uint16_t propcode, PTP_DevicePropDescTypdef* devicepropertydesc) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetDevicePropDesc (phost, propcode, devicepropertydesc)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief The function informs that host has rceived an event * @param pdev: Selected device * @retval None */ __weak void USBH_MTP_EventsCallback(USBH_HandleTypeDef *phost, uint32_t event, uint32_t param) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/