mirror of
https://github.com/STMicroelectronics/stm32-mw-usb-device.git
synced 2026-02-08 20:18:07 -05:00
Release v2.9.0
This commit is contained in:
639
Class/MTP/Src/usbd_mtp.c
Normal file
639
Class/MTP/Src/usbd_mtp.c
Normal file
@@ -0,0 +1,639 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_mtp.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file provides the high layer firmware functions to manage the
|
||||
* following functionalities of the USB MTP Class:
|
||||
* - Initialization and Configuration of high and low layer
|
||||
* - Enumeration as MTP Device (and enumeration for each implemented memory interface)
|
||||
* - OUT/IN data transfer
|
||||
* - Command IN transfer (class requests management)
|
||||
* - Error management
|
||||
*
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
* @verbatim
|
||||
*
|
||||
* ===================================================================
|
||||
* MTP Class Driver Description
|
||||
* ===================================================================
|
||||
* This driver manages the "Universal Serial Bus Class Definitions for Media Transfer Protocol
|
||||
* Revision 1.1 April 6, 2011"
|
||||
* This driver implements the following aspects of the specification:
|
||||
* - Device descriptor management
|
||||
* - Configuration descriptor management
|
||||
* - Enumeration as MTP device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
|
||||
* - Requests management
|
||||
*
|
||||
*
|
||||
* @endverbatim
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_mtp.h"
|
||||
#include "usbd_mtp_storage.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_MTP
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MTP_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_MTP_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_MTP_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_MTP_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
static uint8_t USBD_MTP_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
|
||||
static uint8_t USBD_MTP_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
|
||||
static uint8_t USBD_MTP_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
|
||||
static uint8_t USBD_MTP_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
static uint8_t USBD_MTP_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
static uint8_t *USBD_MTP_GetHSCfgDesc(uint16_t *length);
|
||||
static uint8_t *USBD_MTP_GetFSCfgDesc(uint16_t *length);
|
||||
static uint8_t *USBD_MTP_GetOtherSpeedCfgDesc(uint16_t *length);
|
||||
static uint8_t *USBD_MTP_GetDeviceQualifierDescriptor(uint16_t *length);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MTP_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/* MTP interface class callbacks structure */
|
||||
USBD_ClassTypeDef USBD_MTP =
|
||||
{
|
||||
USBD_MTP_Init,
|
||||
USBD_MTP_DeInit,
|
||||
USBD_MTP_Setup,
|
||||
NULL, /*EP0_TxSent*/
|
||||
NULL, /*EP0_RxReady*/
|
||||
USBD_MTP_DataIn,
|
||||
USBD_MTP_DataOut,
|
||||
NULL, /*SOF */
|
||||
NULL, /*ISOIn*/
|
||||
NULL, /*ISOOut*/
|
||||
USBD_MTP_GetHSCfgDesc,
|
||||
USBD_MTP_GetFSCfgDesc,
|
||||
USBD_MTP_GetOtherSpeedCfgDesc,
|
||||
USBD_MTP_GetDeviceQualifierDescriptor,
|
||||
};
|
||||
|
||||
/* USB MTP device Configuration Descriptor */
|
||||
__ALIGN_BEGIN static uint8_t USBD_MTP_CfgHSDesc[MTP_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
/* Configuration Descriptor */
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
LOBYTE(MTP_CONFIG_DESC_SIZ), /* wTotalLength: Total size of the Config descriptor */
|
||||
HIBYTE(MTP_CONFIG_DESC_SIZ),
|
||||
0x01, /* bNumInterfaces: 1 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
#if (USBD_SELF_POWERED == 1U)
|
||||
0xC0, /* bmAttributes: Bus Powered according to user configuration */
|
||||
#else
|
||||
0x80, /* bmAttributes: Bus Powered according to user configuration */
|
||||
#endif
|
||||
USBD_MAX_POWER, /* MaxPower (mA) */
|
||||
|
||||
/******************** MTP **** interface ********************/
|
||||
MTP_INTERFACE_DESC_SIZE, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
MTP_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x03, /* bNumEndpoints: */
|
||||
USB_MTP_INTRERFACE_CLASS, /* bInterfaceClass: bInterfaceClass: user's interface for MTP */
|
||||
USB_MTP_INTRERFACE_SUB_CLASS, /* bInterfaceSubClass:Abstract Control Model */
|
||||
USB_MTP_INTRERFACE_PROTOCOL, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/******************** MTP Endpoints ********************/
|
||||
MTP_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
|
||||
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
|
||||
MTP_IN_EP, /* Endpoint address (IN, address 1) */
|
||||
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
|
||||
LOBYTE(MTP_DATA_MAX_HS_PACKET_SIZE),
|
||||
HIBYTE(MTP_DATA_MAX_HS_PACKET_SIZE),
|
||||
0x00, /* Polling interval in milliseconds */
|
||||
|
||||
MTP_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
|
||||
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
|
||||
MTP_OUT_EP, /* Endpoint address (OUT, address 1) */
|
||||
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
|
||||
LOBYTE(MTP_DATA_MAX_HS_PACKET_SIZE),
|
||||
HIBYTE(MTP_DATA_MAX_HS_PACKET_SIZE),
|
||||
0x00, /* Polling interval in milliseconds */
|
||||
|
||||
MTP_ENDPOINT_DESC_SIZE, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
|
||||
MTP_CMD_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
USBD_EP_TYPE_INTR, /* bmAttributes: Interrupt endpoint */
|
||||
LOBYTE(MTP_CMD_PACKET_SIZE),
|
||||
HIBYTE(MTP_CMD_PACKET_SIZE),
|
||||
MTP_HS_BINTERVAL /* Polling interval in milliseconds */
|
||||
};
|
||||
|
||||
/* USB MTP device Configuration Descriptor */
|
||||
__ALIGN_BEGIN static uint8_t USBD_MTP_CfgFSDesc[MTP_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
/* Configuration Descriptor */
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
LOBYTE(MTP_CONFIG_DESC_SIZ), /* wTotalLength: Total size of the Config descriptor */
|
||||
HIBYTE(MTP_CONFIG_DESC_SIZ),
|
||||
0x01, /* bNumInterfaces: 1 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
#if (USBD_SELF_POWERED == 1U)
|
||||
0xC0, /* bmAttributes: Bus Powered according to user configuration */
|
||||
#else
|
||||
0x80, /* bmAttributes: Bus Powered according to user configuration */
|
||||
#endif
|
||||
USBD_MAX_POWER, /* MaxPower (mA) */
|
||||
|
||||
/******************** MTP **** interface ********************/
|
||||
MTP_INTERFACE_DESC_SIZE, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
MTP_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x03, /* bNumEndpoints: */
|
||||
USB_MTP_INTRERFACE_CLASS, /* bInterfaceClass: bInterfaceClass: user's interface for MTP */
|
||||
USB_MTP_INTRERFACE_SUB_CLASS, /* bInterfaceSubClass:Abstract Control Model */
|
||||
USB_MTP_INTRERFACE_PROTOCOL, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/******************** MTP Endpoints ********************/
|
||||
MTP_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
|
||||
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
|
||||
MTP_IN_EP, /* Endpoint address (IN, address 1) */
|
||||
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
|
||||
LOBYTE(MTP_DATA_MAX_FS_PACKET_SIZE),
|
||||
HIBYTE(MTP_DATA_MAX_FS_PACKET_SIZE),
|
||||
0x00, /* Polling interval in milliseconds */
|
||||
|
||||
MTP_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
|
||||
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
|
||||
MTP_OUT_EP, /* Endpoint address (OUT, address 1) */
|
||||
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
|
||||
LOBYTE(MTP_DATA_MAX_FS_PACKET_SIZE),
|
||||
HIBYTE(MTP_DATA_MAX_FS_PACKET_SIZE),
|
||||
0x00, /* Polling interval in milliseconds */
|
||||
|
||||
MTP_ENDPOINT_DESC_SIZE, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
|
||||
MTP_CMD_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
USBD_EP_TYPE_INTR, /* bmAttributes: Interrupt endpoint */
|
||||
LOBYTE(MTP_CMD_PACKET_SIZE),
|
||||
HIBYTE(MTP_CMD_PACKET_SIZE),
|
||||
MTP_FS_BINTERVAL /* Polling interval in milliseconds */
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN static uint8_t USBD_MTP_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
|
||||
{
|
||||
USB_LEN_DEV_QUALIFIER_DESC,
|
||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MTP_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Init
|
||||
* Initialize the MTP interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_MTP_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
UNUSED(cfgidx);
|
||||
USBD_MTP_HandleTypeDef *hmtp;
|
||||
|
||||
hmtp = (USBD_MTP_HandleTypeDef *)USBD_malloc(sizeof(USBD_MTP_HandleTypeDef));
|
||||
|
||||
if (hmtp == NULL)
|
||||
{
|
||||
pdev->pClassData = NULL;
|
||||
return (uint8_t)USBD_EMEM;
|
||||
}
|
||||
|
||||
/* Setup the pClassData pointer */
|
||||
pdev->pClassData = (void *)hmtp;
|
||||
|
||||
/* Initialize all variables */
|
||||
(void)USBD_memset(hmtp, 0, sizeof(USBD_MTP_HandleTypeDef));
|
||||
|
||||
/* Setup the max packet size according to selected speed */
|
||||
hmtp->MaxPcktLen = (pdev->dev_speed == USBD_SPEED_HIGH) ? MTP_DATA_MAX_HS_PACKET_SIZE : MTP_DATA_MAX_FS_PACKET_SIZE;
|
||||
|
||||
/* Open EP IN */
|
||||
(void)USBD_LL_OpenEP(pdev, MTP_IN_EP, USBD_EP_TYPE_BULK, hmtp->MaxPcktLen);
|
||||
pdev->ep_in[MTP_IN_EP & 0xFU].is_used = 1U;
|
||||
|
||||
/* Open EP OUT */
|
||||
(void)USBD_LL_OpenEP(pdev, MTP_OUT_EP, USBD_EP_TYPE_BULK, hmtp->MaxPcktLen);
|
||||
pdev->ep_out[MTP_OUT_EP & 0xFU].is_used = 1U;
|
||||
|
||||
/* Open INTR EP IN */
|
||||
(void)USBD_LL_OpenEP(pdev, MTP_CMD_EP, USBD_EP_TYPE_INTR, MTP_CMD_PACKET_SIZE);
|
||||
pdev->ep_in[MTP_CMD_EP & 0xFU].is_used = 1U;
|
||||
|
||||
/* Init the MTP layer */
|
||||
(void)USBD_MTP_STORAGE_Init(pdev);
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_DeInit
|
||||
* DeInitialize the MTP layer
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_MTP_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
UNUSED(cfgidx);
|
||||
|
||||
/* Close EP IN */
|
||||
(void)USBD_LL_CloseEP(pdev, MTP_IN_EP);
|
||||
pdev->ep_in[MTP_IN_EP & 0xFU].is_used = 0U;
|
||||
|
||||
/* Close EP OUT */
|
||||
(void)USBD_LL_CloseEP(pdev, MTP_OUT_EP);
|
||||
pdev->ep_out[MTP_OUT_EP & 0xFU].is_used = 0U;
|
||||
|
||||
/* Close EP Command */
|
||||
(void)USBD_LL_CloseEP(pdev, MTP_CMD_EP);
|
||||
pdev->ep_in[MTP_CMD_EP & 0xFU].is_used = 0U;
|
||||
|
||||
/* De-Init the MTP layer */
|
||||
(void)USBD_MTP_STORAGE_DeInit(pdev);
|
||||
|
||||
/* Free MTP Class Resources */
|
||||
if (pdev->pClassData != NULL)
|
||||
{
|
||||
(void)USBD_free(pdev->pClassData);
|
||||
pdev->pClassData = NULL;
|
||||
}
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Setup
|
||||
* Handle the MTP specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_MTP_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
USBD_StatusTypeDef ret = USBD_OK;
|
||||
uint16_t len = 0U;
|
||||
|
||||
if (hmtp == NULL)
|
||||
{
|
||||
return (uint8_t)USBD_FAIL;
|
||||
}
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
/* Class request */
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case MTP_REQ_CANCEL:
|
||||
len = MIN(hmtp->MaxPcktLen, req->wLength);
|
||||
(void)USBD_CtlPrepareRx(pdev, (uint8_t *)(hmtp->rx_buff), len);
|
||||
break;
|
||||
|
||||
case MTP_REQ_GET_EXT_EVENT_DATA:
|
||||
break;
|
||||
|
||||
case MTP_REQ_RESET:
|
||||
/* Stop low layer file system operations if any */
|
||||
USBD_MTP_STORAGE_Cancel(pdev, MTP_PHASE_IDLE);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff, hmtp->MaxPcktLen);
|
||||
break;
|
||||
|
||||
case MTP_REQ_GET_DEVICE_STATUS:
|
||||
switch (hmtp->MTP_ResponsePhase)
|
||||
{
|
||||
case MTP_READ_DATA :
|
||||
len = 4U;
|
||||
hmtp->dev_status = ((uint32_t)MTP_RESPONSE_DEVICE_BUSY << 16) | len;
|
||||
break;
|
||||
|
||||
case MTP_RECEIVE_DATA :
|
||||
len = 4U;
|
||||
hmtp->dev_status = ((uint32_t)MTP_RESPONSE_TRANSACTION_CANCELLED << 16) | len;
|
||||
break;
|
||||
|
||||
case MTP_PHASE_IDLE :
|
||||
len = 4U;
|
||||
hmtp->dev_status = ((uint32_t)MTP_RESPONSE_OK << 16) | len;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmtp->dev_status, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Interface & Endpoint request */
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_INTERFACE :
|
||||
|
||||
if (pdev->dev_state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
hmtp->alt_setting = 0U;
|
||||
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmtp->alt_setting, 1U);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE :
|
||||
if (pdev->dev_state != USBD_STATE_CONFIGURED)
|
||||
{
|
||||
USBD_CtlError(pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
|
||||
/* Re-activate the EP */
|
||||
(void)USBD_LL_CloseEP(pdev, (uint8_t)req->wIndex);
|
||||
|
||||
if ((((uint8_t)req->wIndex) & 0x80U) == 0x80U)
|
||||
{
|
||||
(void)USBD_LL_OpenEP(pdev, ((uint8_t)req->wIndex), USBD_EP_TYPE_BULK, hmtp->MaxPcktLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USBD_LL_OpenEP(pdev, ((uint8_t)req->wIndex), USBD_EP_TYPE_BULK, hmtp->MaxPcktLen);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (uint8_t)ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_DataIn
|
||||
* Data sent on non-control IN endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_MTP_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
UNUSED(epnum);
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint16_t len;
|
||||
|
||||
if (epnum == (MTP_IN_EP & 0x7FU))
|
||||
{
|
||||
switch (hmtp->MTP_ResponsePhase)
|
||||
{
|
||||
case MTP_RESPONSE_PHASE :
|
||||
(void)USBD_MTP_STORAGE_SendContainer(pdev, REP_TYPE);
|
||||
|
||||
/* prepare to receive next operation */
|
||||
len = MIN(hmtp->MaxPcktLen, pdev->request.wLength);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff, len);
|
||||
hmtp->MTP_ResponsePhase = MTP_PHASE_IDLE;
|
||||
break;
|
||||
case MTP_READ_DATA :
|
||||
(void)USBD_MTP_STORAGE_ReadData(pdev);
|
||||
|
||||
/* prepare to receive next operation */
|
||||
len = MIN(hmtp->MaxPcktLen, pdev->request.wLength);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_IN_EP, (uint8_t *)&hmtp->rx_buff, len);
|
||||
break;
|
||||
case MTP_PHASE_IDLE :
|
||||
/* prepare to receive next operation */
|
||||
len = MIN(hmtp->MaxPcktLen, pdev->request.wLength);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff, len);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_DataOut
|
||||
* Data received on non-control Out endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_MTP_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
UNUSED(epnum);
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint16_t len;
|
||||
|
||||
(void)USBD_MTP_STORAGE_ReceiveOpt(pdev);
|
||||
|
||||
switch (hmtp->MTP_ResponsePhase)
|
||||
{
|
||||
case MTP_RESPONSE_PHASE :
|
||||
|
||||
if (hmtp->ResponseLength == MTP_CONT_HEADER_SIZE)
|
||||
{
|
||||
(void)USBD_MTP_STORAGE_SendContainer(pdev, REP_TYPE);
|
||||
hmtp->MTP_ResponsePhase = MTP_PHASE_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USBD_MTP_STORAGE_SendContainer(pdev, DATA_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
case MTP_READ_DATA :
|
||||
(void)USBD_MTP_STORAGE_ReadData(pdev);
|
||||
break;
|
||||
|
||||
case MTP_RECEIVE_DATA :
|
||||
(void)USBD_MTP_STORAGE_ReceiveData(pdev);
|
||||
|
||||
/* prepare endpoint to receive operations */
|
||||
len = MIN(hmtp->MaxPcktLen, pdev->request.wLength);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff, len);
|
||||
break;
|
||||
|
||||
case MTP_PHASE_IDLE :
|
||||
/* prepare to receive next operation */
|
||||
len = MIN(hmtp->MaxPcktLen, pdev->request.wLength);
|
||||
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_GetHSCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_MTP_GetHSCfgDesc(uint16_t *length)
|
||||
{
|
||||
*length = (uint16_t)sizeof(USBD_MTP_CfgHSDesc);
|
||||
return USBD_MTP_CfgHSDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_GetFSCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_MTP_GetFSCfgDesc(uint16_t *length)
|
||||
{
|
||||
*length = (uint16_t)sizeof(USBD_MTP_CfgFSDesc);
|
||||
return USBD_MTP_CfgFSDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_GetOtherSpeedCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_MTP_GetOtherSpeedCfgDesc(uint16_t *length)
|
||||
{
|
||||
*length = (uint16_t)sizeof(USBD_MTP_CfgFSDesc);
|
||||
return USBD_MTP_CfgFSDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_GetDeviceQualifierDescriptor
|
||||
* return Device Qualifier descriptor
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_MTP_GetDeviceQualifierDescriptor(uint16_t *length)
|
||||
{
|
||||
*length = (uint16_t)(sizeof(USBD_MTP_DeviceQualifierDesc));
|
||||
return USBD_MTP_DeviceQualifierDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_RegisterInterface
|
||||
* @param pdev: device instance
|
||||
* @param fops: CD Interface callback
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_MTP_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_MTP_ItfTypeDef *fops)
|
||||
{
|
||||
if (fops == NULL)
|
||||
{
|
||||
return (uint8_t)USBD_FAIL;
|
||||
}
|
||||
|
||||
pdev->pUserData = fops;
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
347
Class/MTP/Src/usbd_mtp_if_template.c
Normal file
347
Class/MTP/Src/usbd_mtp_if_template.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_mtp_if.c
|
||||
* @author MCD Application Team
|
||||
* @brief Source file for USBD MTP file list_files.
|
||||
******************************************************************************
|
||||
* @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_if_template.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/*
|
||||
static FILE MyFile;
|
||||
static FATFS SDFatFs;
|
||||
static char SDPath[4];
|
||||
static FolderLevel Fold_Lvl;
|
||||
static FOLD_INFTypeDef FoldStruct;
|
||||
static FILE_INFTypeDef FileStruct;
|
||||
static SD_Object_TypeDef sd_object;
|
||||
*/
|
||||
extern USBD_HandleTypeDef USBD_Device;
|
||||
|
||||
uint32_t idx[200];
|
||||
uint32_t parent;
|
||||
/* static char path[255]; */
|
||||
uint32_t sc_buff[MTP_IF_SCRATCH_BUFF_SZE / 4U];
|
||||
uint32_t sc_len = 0U;
|
||||
uint32_t pckt_cnt = 1U;
|
||||
uint32_t foldsize;
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint8_t USBD_MTP_Itf_Init(void);
|
||||
static uint8_t USBD_MTP_Itf_DeInit(void);
|
||||
static uint32_t USBD_MTP_Itf_ReadData(uint32_t Param1, uint8_t *buff, MTP_DataLengthTypeDef *data_length);
|
||||
static uint16_t USBD_MTP_Itf_Create_NewObject(MTP_ObjectInfoTypeDef ObjectInfo, uint32_t objhandle);
|
||||
|
||||
static uint32_t USBD_MTP_Itf_GetIdx(uint32_t Param3, uint32_t *obj_handle);
|
||||
static uint32_t USBD_MTP_Itf_GetParentObject(uint32_t Param);
|
||||
static uint16_t USBD_MTP_Itf_GetObjectFormat(uint32_t Param);
|
||||
static uint8_t USBD_MTP_Itf_GetObjectName_len(uint32_t Param);
|
||||
static void USBD_MTP_Itf_GetObjectName(uint32_t Param, uint8_t obj_len, uint16_t *buf);
|
||||
static uint32_t USBD_MTP_Itf_GetObjectSize(uint32_t Param);
|
||||
static uint64_t USBD_MTP_Itf_GetMaxCapability(void);
|
||||
static uint64_t USBD_MTP_Itf_GetFreeSpaceInBytes(void);
|
||||
static uint32_t USBD_MTP_Itf_GetNewIndex(uint16_t objformat);
|
||||
static void USBD_MTP_Itf_WriteData(uint16_t len, uint8_t *buff);
|
||||
static uint32_t USBD_MTP_Itf_GetContainerLength(uint32_t Param1);
|
||||
static uint16_t USBD_MTP_Itf_DeleteObject(uint32_t Param1);
|
||||
|
||||
static void USBD_MTP_Itf_Cancel(uint32_t Phase);
|
||||
/* static uint32_t USBD_MTP_Get_idx_to_delete(uint32_t Param, uint8_t *tab); */
|
||||
|
||||
USBD_MTP_ItfTypeDef USBD_MTP_fops =
|
||||
{
|
||||
USBD_MTP_Itf_Init,
|
||||
USBD_MTP_Itf_DeInit,
|
||||
USBD_MTP_Itf_ReadData,
|
||||
USBD_MTP_Itf_Create_NewObject,
|
||||
USBD_MTP_Itf_GetIdx,
|
||||
USBD_MTP_Itf_GetParentObject,
|
||||
USBD_MTP_Itf_GetObjectFormat,
|
||||
USBD_MTP_Itf_GetObjectName_len,
|
||||
USBD_MTP_Itf_GetObjectName,
|
||||
USBD_MTP_Itf_GetObjectSize,
|
||||
USBD_MTP_Itf_GetMaxCapability,
|
||||
USBD_MTP_Itf_GetFreeSpaceInBytes,
|
||||
USBD_MTP_Itf_GetNewIndex,
|
||||
USBD_MTP_Itf_WriteData,
|
||||
USBD_MTP_Itf_GetContainerLength,
|
||||
USBD_MTP_Itf_DeleteObject,
|
||||
USBD_MTP_Itf_Cancel,
|
||||
sc_buff,
|
||||
MTP_IF_SCRATCH_BUFF_SZE,
|
||||
};
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_Init
|
||||
* Initialize the file system Layer
|
||||
* @param None
|
||||
* @retval status value
|
||||
*/
|
||||
static uint8_t USBD_MTP_Itf_Init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_DeInit
|
||||
* Uninitialize the file system Layer
|
||||
* @param None
|
||||
* @retval status value
|
||||
*/
|
||||
static uint8_t USBD_MTP_Itf_DeInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetIdx
|
||||
* Get all object handle
|
||||
* @param Param3: current object handle
|
||||
* @param obj_handle: all objects handle (subfolders/files) in current object
|
||||
* @retval number of object handle in current object
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_GetIdx(uint32_t Param3, uint32_t *obj_handle)
|
||||
{
|
||||
uint32_t count = 0U;
|
||||
UNUSED(Param3);
|
||||
UNUSED(obj_handle);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetParentObject
|
||||
* Get parent object
|
||||
* @param Param: object handle (object index)
|
||||
* @retval parent object
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_GetParentObject(uint32_t Param)
|
||||
{
|
||||
uint32_t parentobj = 0U;
|
||||
UNUSED(Param);
|
||||
|
||||
return parentobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetObjectFormat
|
||||
* Get object format
|
||||
* @param Param: object handle (object index)
|
||||
* @retval object format
|
||||
*/
|
||||
static uint16_t USBD_MTP_Itf_GetObjectFormat(uint32_t Param)
|
||||
{
|
||||
uint16_t objformat = 0U;
|
||||
UNUSED(Param);
|
||||
|
||||
return objformat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetObjectName_len
|
||||
* Get object name length
|
||||
* @param Param: object handle (object index)
|
||||
* @retval object name length
|
||||
*/
|
||||
static uint8_t USBD_MTP_Itf_GetObjectName_len(uint32_t Param)
|
||||
{
|
||||
uint8_t obj_len = 0U;
|
||||
UNUSED(Param);
|
||||
|
||||
return obj_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetObjectName
|
||||
* Get object name
|
||||
* @param Param: object handle (object index)
|
||||
* @param obj_len: length of object name
|
||||
* @param buf: pointer to object name
|
||||
* @retval object size in SD card
|
||||
*/
|
||||
static void USBD_MTP_Itf_GetObjectName(uint32_t Param, uint8_t obj_len, uint16_t *buf)
|
||||
{
|
||||
UNUSED(Param);
|
||||
UNUSED(obj_len);
|
||||
UNUSED(buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetObjectSize
|
||||
* Get size of current object
|
||||
* @param Param: object handle (object index)
|
||||
* @retval object size in SD card
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_GetObjectSize(uint32_t Param)
|
||||
{
|
||||
uint32_t ObjCompSize = 0U;
|
||||
UNUSED(Param);
|
||||
|
||||
return ObjCompSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_Create_NewObject
|
||||
* Create new object in SD card and store necessary information for future use
|
||||
* @param ObjectInfo: object information to use
|
||||
* @param objhandle: object handle (object index)
|
||||
* @retval None
|
||||
*/
|
||||
static uint16_t USBD_MTP_Itf_Create_NewObject(MTP_ObjectInfoTypeDef ObjectInfo, uint32_t objhandle)
|
||||
{
|
||||
uint16_t rep_code = 0U;
|
||||
UNUSED(ObjectInfo);
|
||||
UNUSED(objhandle);
|
||||
|
||||
return rep_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetMaxCapability
|
||||
* Get max capability in SD card
|
||||
* @param None
|
||||
* @retval max capability
|
||||
*/
|
||||
static uint64_t USBD_MTP_Itf_GetMaxCapability(void)
|
||||
{
|
||||
uint64_t max_cap = 0U;
|
||||
|
||||
return max_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetFreeSpaceInBytes
|
||||
* Get free space in bytes in SD card
|
||||
* @param None
|
||||
* @retval free space in bytes
|
||||
*/
|
||||
static uint64_t USBD_MTP_Itf_GetFreeSpaceInBytes(void)
|
||||
{
|
||||
uint64_t f_space_inbytes = 0U;
|
||||
|
||||
return f_space_inbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetNewIndex
|
||||
* Create new object handle
|
||||
* @param objformat: object format
|
||||
* @retval object handle
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_GetNewIndex(uint16_t objformat)
|
||||
{
|
||||
uint32_t n_index = 0U;
|
||||
UNUSED(objformat);
|
||||
|
||||
return n_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_WriteData
|
||||
* Write file data to SD card
|
||||
* @param len: size of data to write
|
||||
* @param buff: data to write in SD card
|
||||
* @retval None
|
||||
*/
|
||||
static void USBD_MTP_Itf_WriteData(uint16_t len, uint8_t *buff)
|
||||
{
|
||||
UNUSED(len);
|
||||
UNUSED(buff);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_GetContainerLength
|
||||
* Get length of generic container
|
||||
* @param Param1: object handle
|
||||
* @retval length of generic container
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_GetContainerLength(uint32_t Param1)
|
||||
{
|
||||
uint32_t length = 0U;
|
||||
UNUSED(Param1);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_DeleteObject
|
||||
* delete object from SD card
|
||||
* @param Param1: object handle (file/folder index)
|
||||
* @retval response code
|
||||
*/
|
||||
static uint16_t USBD_MTP_Itf_DeleteObject(uint32_t Param1)
|
||||
{
|
||||
uint16_t rep_code = 0U;
|
||||
UNUSED(Param1);
|
||||
|
||||
return rep_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Get_idx_to_delete
|
||||
* Get all files/foldres index to delete with descending order ( max depth)
|
||||
* @param Param: object handle (file/folder index)
|
||||
* @param tab: pointer to list of files/folders to delete
|
||||
* @retval Number of files/folders to delete
|
||||
*/
|
||||
/* static uint32_t USBD_MTP_Get_idx_to_delete(uint32_t Param, uint8_t *tab)
|
||||
{
|
||||
uint32_t cnt = 0U;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_ReadData
|
||||
* Read data from SD card
|
||||
* @param Param1: object handle
|
||||
* @param buff: pointer to data to be read
|
||||
* @param temp_length: current data size read
|
||||
* @retval necessary information for next read/finish reading
|
||||
*/
|
||||
static uint32_t USBD_MTP_Itf_ReadData(uint32_t Param1, uint8_t *buff, MTP_DataLengthTypeDef *data_length)
|
||||
{
|
||||
UNUSED(Param1);
|
||||
UNUSED(buff);
|
||||
UNUSED(data_length);
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_Itf_Cancel
|
||||
* Close opened folder/file while cancelling transaction
|
||||
* @param MTP_ResponsePhase: MTP current state
|
||||
* @retval None
|
||||
*/
|
||||
static void USBD_MTP_Itf_Cancel(uint32_t Phase)
|
||||
{
|
||||
UNUSED(Phase);
|
||||
|
||||
/* Make sure to close open file while canceling transaction */
|
||||
|
||||
return;
|
||||
}
|
||||
1266
Class/MTP/Src/usbd_mtp_opt.c
Normal file
1266
Class/MTP/Src/usbd_mtp_opt.c
Normal file
File diff suppressed because it is too large
Load Diff
456
Class/MTP/Src/usbd_mtp_storage.c
Normal file
456
Class/MTP/Src/usbd_mtp_storage.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_mtp_storage.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file provides all the transfer command functions for MTP
|
||||
******************************************************************************
|
||||
* @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_storage.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static MTP_DataLengthTypeDef MTP_DataLength;
|
||||
static MTP_READ_DATA_STATUS ReadDataStatus;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint8_t USBD_MTP_STORAGE_DecodeOperations(USBD_HandleTypeDef *pdev);
|
||||
static uint8_t USBD_MTP_STORAGE_ReceiveContainer(USBD_HandleTypeDef *pdev, uint32_t *pDst, uint32_t len);
|
||||
static uint8_t USBD_MTP_STORAGE_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf, uint32_t len);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_Init
|
||||
* Initialize the MTP USB Layer
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_Init(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
|
||||
/* Initialize the HW layyer of the file system */
|
||||
(void)((USBD_MTP_ItfTypeDef *)pdev->pUserData)->Init();
|
||||
|
||||
/* Prepare EP to Receive First Operation */
|
||||
(void)USBD_LL_PrepareReceive(pdev, MTP_OUT_EP, (uint8_t *)&hmtp->rx_buff,
|
||||
hmtp->MaxPcktLen);
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_DeInit
|
||||
* Uninitialize the MTP Machine
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_DeInit(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
|
||||
/* DeInit physical Interface components */
|
||||
hmtp->MTP_SessionState = MTP_SESSION_NOT_OPENED;
|
||||
|
||||
/* Stop low layer file system operations if any */
|
||||
USBD_MTP_STORAGE_Cancel(pdev, MTP_PHASE_IDLE);
|
||||
|
||||
/* Free low layer file system resources */
|
||||
(void)((USBD_MTP_ItfTypeDef *)pdev->pUserData)->DeInit();
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_ReadData
|
||||
* Read data from device objects and send it to the host
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_ReadData(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint32_t *data_buff;
|
||||
|
||||
/* Get the data buffer pointer from the low layer interface */
|
||||
data_buff = ((USBD_MTP_ItfTypeDef *)pdev->pUserData)->ScratchBuff;
|
||||
|
||||
switch (ReadDataStatus)
|
||||
{
|
||||
case READ_FIRST_DATA:
|
||||
/* Reset the data length */
|
||||
MTP_DataLength.temp_length = 0U;
|
||||
|
||||
/* Perform the low layer read operation on the scratch buffer */
|
||||
(void)((USBD_MTP_ItfTypeDef *)pdev->pUserData)->ReadData(hmtp->OperationsContainer.Param1,
|
||||
(uint8_t *)data_buff, &MTP_DataLength);
|
||||
|
||||
/* Add the container header to the data buffer */
|
||||
(void)USBD_memcpy((uint8_t *)data_buff, (uint8_t *)&hmtp->GenericContainer, MTP_CONT_HEADER_SIZE);
|
||||
|
||||
/* Start USB data transmission to the host */
|
||||
(void)USBD_MTP_STORAGE_SendData(pdev, (uint8_t *)data_buff,
|
||||
MTP_DataLength.readbytes + MTP_CONT_HEADER_SIZE);
|
||||
|
||||
/* Check if this will be the last packet to send ? */
|
||||
if (MTP_DataLength.readbytes < ((uint32_t)hmtp->MaxPcktLen - MTP_CONT_HEADER_SIZE))
|
||||
{
|
||||
/* Move to response phase */
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continue to the next packets sending */
|
||||
ReadDataStatus = READ_REST_OF_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case READ_REST_OF_DATA:
|
||||
/* Perform the low layer read operation on the scratch buffer */
|
||||
(void)((USBD_MTP_ItfTypeDef *)pdev->pUserData)->ReadData(hmtp->OperationsContainer.Param1,
|
||||
(uint8_t *)data_buff, &MTP_DataLength);
|
||||
|
||||
/* Check if more data need to be sent */
|
||||
if (MTP_DataLength.temp_length == MTP_DataLength.totallen)
|
||||
{
|
||||
/* Start USB data transmission to the host */
|
||||
(void)USBD_MTP_STORAGE_SendData(pdev, (uint8_t *)data_buff, MTP_DataLength.readbytes);
|
||||
|
||||
/* Move to response phase */
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
|
||||
/* Reset the stat machine */
|
||||
ReadDataStatus = READ_FIRST_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start USB data transmission to the host */
|
||||
(void)USBD_MTP_STORAGE_SendData(pdev, (uint8_t *)data_buff, MTP_DataLength.readbytes);
|
||||
|
||||
/* Keep the state machine into sending next packet of data */
|
||||
ReadDataStatus = READ_REST_OF_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_SendContainer
|
||||
* Send generic container to the host
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_SendContainer(USBD_HandleTypeDef *pdev, MTP_CONTAINER_TYPE CONT_TYPE)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
switch (CONT_TYPE)
|
||||
{
|
||||
case DATA_TYPE:
|
||||
/* send header + data : hmtp->ResponseLength = header size + data size */
|
||||
(void)USBD_MTP_STORAGE_SendData(pdev, (uint8_t *)&hmtp->GenericContainer, hmtp->ResponseLength);
|
||||
break;
|
||||
case REP_TYPE:
|
||||
/* send header without data */
|
||||
hmtp->GenericContainer.code = (uint16_t)hmtp->ResponseCode;
|
||||
hmtp->ResponseLength = MTP_CONT_HEADER_SIZE;
|
||||
hmtp->GenericContainer.length = hmtp->ResponseLength;
|
||||
hmtp->GenericContainer.type = MTP_CONT_TYPE_RESPONSE;
|
||||
|
||||
(void)USBD_MTP_STORAGE_SendData(pdev, (uint8_t *)&hmtp->GenericContainer, hmtp->ResponseLength);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_ReceiveOpt
|
||||
* Data length Packet Received from host
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_ReceiveOpt(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint32_t *pMsgBuffer;
|
||||
MTP_DataLength.rx_length = USBD_GetRxCount(pdev, MTP_OUT_EP);
|
||||
switch (hmtp->RECEIVE_DATA_STATUS)
|
||||
{
|
||||
case RECEIVE_REST_OF_DATA:
|
||||
/* we don't need to do anything here because we receive only data without operation header*/
|
||||
break;
|
||||
|
||||
case RECEIVE_FIRST_DATA:
|
||||
/* Expected Data Length Packet Received */
|
||||
pMsgBuffer = (uint32_t *) &hmtp->OperationsContainer;
|
||||
|
||||
/* Fill hmtp->OperationsContainer Data Buffer from USB Buffer */
|
||||
(void)USBD_MTP_STORAGE_ReceiveContainer(pdev, pMsgBuffer, MTP_DataLength.rx_length);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Expected Data Length Packet Received */
|
||||
pMsgBuffer = (uint32_t *) &hmtp->OperationsContainer;
|
||||
|
||||
/* Fill hmtp->OperationsContainer Data Buffer from USB Buffer */
|
||||
(void)USBD_MTP_STORAGE_ReceiveContainer(pdev, pMsgBuffer, MTP_DataLength.rx_length);
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
break;
|
||||
|
||||
}
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_ReceiveData
|
||||
* Receive objects or object info from host
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
uint8_t USBD_MTP_STORAGE_ReceiveData(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
switch (hmtp->RECEIVE_DATA_STATUS)
|
||||
{
|
||||
case RECEIVE_COMMAND_DATA :
|
||||
if (hmtp->OperationsContainer.type == MTP_CONT_TYPE_COMMAND)
|
||||
{
|
||||
MTP_DataLength.temp_length = 0;
|
||||
MTP_DataLength.prv_len = 0;
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case RECEIVE_FIRST_DATA :
|
||||
if (hmtp->OperationsContainer.type == MTP_CONT_TYPE_DATA)
|
||||
{
|
||||
MTP_DataLength.totallen = hmtp->OperationsContainer.length;
|
||||
MTP_DataLength.temp_length = MTP_DataLength.rx_length;
|
||||
MTP_DataLength.rx_length = MTP_DataLength.temp_length - MTP_CONT_HEADER_SIZE;
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
|
||||
if (MTP_DataLength.temp_length < hmtp->MaxPcktLen) /* we received all data, we don't need to go to next state */
|
||||
{
|
||||
hmtp->RECEIVE_DATA_STATUS = SEND_RESPONSE;
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
|
||||
/* send response header after receiving all data successfully */
|
||||
(void)USBD_MTP_STORAGE_SendContainer(pdev, DATA_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RECEIVE_REST_OF_DATA :
|
||||
MTP_DataLength.prv_len = MTP_DataLength.temp_length - MTP_CONT_HEADER_SIZE;
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
MTP_DataLength.temp_length = MTP_DataLength.temp_length + MTP_DataLength.rx_length;
|
||||
|
||||
if (MTP_DataLength.temp_length == MTP_DataLength.totallen) /* we received all data*/
|
||||
{
|
||||
hmtp->RECEIVE_DATA_STATUS = SEND_RESPONSE;
|
||||
(void)USBD_MTP_STORAGE_DecodeOperations(pdev);
|
||||
|
||||
/* send response header after receiving all data successfully */
|
||||
(void)USBD_MTP_STORAGE_SendContainer(pdev, DATA_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_DecodeOperations
|
||||
* Parse the operations and Process operations
|
||||
* @param pdev: device instance
|
||||
* @retval status value
|
||||
*/
|
||||
static uint8_t USBD_MTP_STORAGE_DecodeOperations(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
switch (hmtp->OperationsContainer.code)
|
||||
{
|
||||
case MTP_OP_GET_DEVICE_INFO:
|
||||
USBD_MTP_OPT_GetDeviceInfo(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_OPEN_SESSION:
|
||||
USBD_MTP_OPT_CreateObjectHandle(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_STORAGE_IDS:
|
||||
USBD_MTP_OPT_GetStorageIDS(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_STORAGE_INFO:
|
||||
USBD_MTP_OPT_GetStorageInfo(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_HANDLES:
|
||||
USBD_MTP_OPT_GetObjectHandle(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_INFO:
|
||||
USBD_MTP_OPT_GetObjectInfo(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_PROP_REFERENCES:
|
||||
USBD_MTP_OPT_GetObjectReferences(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_PROPS_SUPPORTED:
|
||||
USBD_MTP_OPT_GetObjectPropSupp(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_PROP_DESC:
|
||||
USBD_MTP_OPT_GetObjectPropDesc(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_PROPLIST:
|
||||
USBD_MTP_OPT_GetObjectPropList(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT_PROP_VALUE:
|
||||
USBD_MTP_OPT_GetObjectPropValue(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_DEVICE_PROP_DESC:
|
||||
USBD_MTP_OPT_GetDevicePropDesc(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
case MTP_OP_GET_OBJECT:
|
||||
USBD_MTP_OPT_GetObject(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_READ_DATA;
|
||||
break;
|
||||
|
||||
case MTP_OP_SEND_OBJECT_INFO:
|
||||
USBD_MTP_OPT_SendObjectInfo(pdev, (uint8_t *)(hmtp->rx_buff), MTP_DataLength.prv_len);
|
||||
hmtp->MTP_ResponsePhase = MTP_RECEIVE_DATA;
|
||||
break;
|
||||
|
||||
case MTP_OP_SEND_OBJECT:
|
||||
USBD_MTP_OPT_SendObject(pdev, (uint8_t *)(hmtp->rx_buff), MTP_DataLength.rx_length);
|
||||
hmtp->MTP_ResponsePhase = MTP_RECEIVE_DATA;
|
||||
break;
|
||||
|
||||
case MTP_OP_DELETE_OBJECT:
|
||||
USBD_MTP_OPT_DeleteObject(pdev);
|
||||
hmtp->MTP_ResponsePhase = MTP_RESPONSE_PHASE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_ReceiveContainer
|
||||
* Receive the Data from USB BulkOut Buffer to Pointer
|
||||
* @param pdev: device instance
|
||||
* @param pDst: destination address to copy the buffer
|
||||
* @param len: length of data to copy
|
||||
* @retval status value
|
||||
*/
|
||||
static uint8_t USBD_MTP_STORAGE_ReceiveContainer(USBD_HandleTypeDef *pdev,
|
||||
uint32_t *pDst, uint32_t len)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint32_t Counter;
|
||||
uint32_t *pdst = pDst;
|
||||
|
||||
for (Counter = 0; Counter < len; Counter++)
|
||||
{
|
||||
*pdst = (hmtp->rx_buff[Counter]);
|
||||
pdst++;
|
||||
}
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_Cancel
|
||||
* Reinitialize all states and cancel transfer through Bulk transfer
|
||||
* @param pdev: device instance
|
||||
* @param MTP_ResponsePhase: MTP current state
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_MTP_STORAGE_Cancel(USBD_HandleTypeDef *pdev,
|
||||
MTP_ResponsePhaseTypeDef MTP_ResponsePhase)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
|
||||
hmtp->MTP_ResponsePhase = MTP_PHASE_IDLE;
|
||||
ReadDataStatus = READ_FIRST_DATA;
|
||||
hmtp->RECEIVE_DATA_STATUS = RECEIVE_IDLE_STATE;
|
||||
|
||||
if (MTP_ResponsePhase == MTP_RECEIVE_DATA)
|
||||
{
|
||||
((USBD_MTP_ItfTypeDef *)pdev->pUserData)->Cancel(1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
((USBD_MTP_ItfTypeDef *)pdev->pUserData)->Cancel(0U);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_MTP_STORAGE_SendData
|
||||
* Send the data on bulk-in EP
|
||||
* @param pdev: device instance
|
||||
* @param buf: pointer to data buffer
|
||||
* @param len: Data Length
|
||||
* @retval status value
|
||||
*/
|
||||
static uint8_t USBD_MTP_STORAGE_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf,
|
||||
uint32_t len)
|
||||
{
|
||||
USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassData;
|
||||
uint32_t length = MIN(hmtp->GenericContainer.length, len);
|
||||
|
||||
(void)USBD_LL_Transmit(pdev, MTP_IN_EP, buf, length);
|
||||
|
||||
return (uint8_t)USBD_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user