dd38d90724
This compiles and links, but hasn't been tested on a board yet and even if it was run, it doesn't currently do anything.
1066 lines
33 KiB
C
1066 lines
33 KiB
C
/**
|
|
******************************************************************************
|
|
* @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
|
|
*
|
|
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
|
*
|
|
* 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****/
|