first commit

This commit is contained in:
2022-11-08 16:13:55 +01:00
commit f838fa66c4
2500 changed files with 2237507 additions and 0 deletions
@@ -0,0 +1,210 @@
/**
******************************************************************************
* @file usbd_audio.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief header file for the usbd_audio.c file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_AUDIO_H
#define __USB_AUDIO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief This file is the Header file for usbd_audio.c
* @{
*/
/** @defgroup USBD_AUDIO_Exported_Defines
* @{
*/
#define AUDIO_OUT_EP 0x01
#define USB_AUDIO_CONFIG_DESC_SIZ 109
#define AUDIO_INTERFACE_DESC_SIZE 9
#define USB_AUDIO_DESC_SIZ 0x09
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07
#define AUDIO_DESCRIPTOR_TYPE 0x21
#define USB_DEVICE_CLASS_AUDIO 0x01
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
#define AUDIO_PROTOCOL_UNDEFINED 0x00
#define AUDIO_STREAMING_GENERAL 0x01
#define AUDIO_STREAMING_FORMAT_TYPE 0x02
/* Audio Descriptor Types */
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
/* Audio Control Interface Descriptor Subtypes */
#define AUDIO_CONTROL_HEADER 0x01
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03
#define AUDIO_CONTROL_FEATURE_UNIT 0x06
#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07
#define AUDIO_CONTROL_MUTE 0x0001
#define AUDIO_FORMAT_TYPE_I 0x01
#define AUDIO_FORMAT_TYPE_III 0x03
#define AUDIO_ENDPOINT_GENERAL 0x01
#define AUDIO_REQ_GET_CUR 0x81
#define AUDIO_REQ_SET_CUR 0x01
#define AUDIO_OUT_STREAMING_CTRL 0x02
#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ * 2 * 2) /1000))
#define AUDIO_DEFAULT_VOLUME 70
/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make sure
that it is an even number and higher than 3 */
#define AUDIO_OUT_PACKET_NUM 80
/* Total size of the audio transfer buffer */
#define AUDIO_TOTAL_BUF_SIZE ((uint32_t)(AUDIO_OUT_PACKET * AUDIO_OUT_PACKET_NUM))
/* Audio Commands enumeration */
typedef enum
{
AUDIO_CMD_START = 1,
AUDIO_CMD_PLAY,
AUDIO_CMD_STOP,
}AUDIO_CMD_TypeDef;
typedef enum
{
AUDIO_OFFSET_NONE = 0,
AUDIO_OFFSET_HALF,
AUDIO_OFFSET_FULL,
AUDIO_OFFSET_UNKNOWN,
}
AUDIO_OffsetTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef struct
{
uint8_t cmd;
uint8_t data[USB_MAX_EP0_SIZE];
uint8_t len;
uint8_t unit;
}
USBD_AUDIO_ControlTypeDef;
typedef struct
{
__IO uint32_t alt_setting;
uint8_t buffer[AUDIO_TOTAL_BUF_SIZE];
AUDIO_OffsetTypeDef offset;
uint8_t rd_enable;
uint16_t rd_ptr;
uint16_t wr_ptr;
USBD_AUDIO_ControlTypeDef control;
}
USBD_AUDIO_HandleTypeDef;
typedef struct
{
int8_t (*Init) (uint32_t AudioFreq, uint32_t Volume, uint32_t options);
int8_t (*DeInit) (uint32_t options);
int8_t (*AudioCmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd);
int8_t (*VolumeCtl) (uint8_t vol);
int8_t (*MuteCtl) (uint8_t cmd);
int8_t (*PeriodicTC) (uint8_t cmd);
int8_t (*GetState) (void);
}USBD_AUDIO_ItfTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_AUDIO;
#define USBD_AUDIO_CLASS &USBD_AUDIO
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_AUDIO_RegisterInterface (USBD_HandleTypeDef *pdev,
USBD_AUDIO_ItfTypeDef *fops);
void USBD_AUDIO_Sync (USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_AUDIO_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,53 @@
/**
******************************************************************************
* @file usbd_audio_if_template.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Header for usbd_audio_if_template.c file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_AUDIO_IF_TEMPLATE_H
#define __USBD_AUDIO_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_audio.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
extern USBD_AUDIO_ItfTypeDef USBD_AUDIO_Template_fops;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __USBD_AUDIO_IF_TEMPLATE_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,791 @@
/**
******************************************************************************
* @file usbd_audio.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief This file provides the Audio core functions.
*
* @verbatim
*
* ===================================================================
* AUDIO Class Description
* ===================================================================
* This driver manages the Audio Class 1.0 following the "USB Device Class Definition for
* Audio Devices V1.0 Mar 18, 98".
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Standard AC Interface Descriptor management
* - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode)
* - 1 Audio Streaming Endpoint
* - 1 Audio Terminal Input (1 channel)
* - Audio Class-Specific AC Interfaces
* - Audio Class-Specific AS Interfaces
* - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute)
* - Audio Feature Unit (limited to Mute control)
* - Audio Synchronization type: Asynchronous
* - Single fixed audio sampling rate (configurable in usbd_conf.h file)
* The current audio class version supports the following audio features:
* - Pulse Coded Modulation (PCM) format
* - sampling rate: 48KHz.
* - Bit resolution: 16
* - Number of channels: 2
* - No volume control
* - Mute/Unmute capability
* - Asynchronous Endpoints
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_audio.h"
#include "usbd_desc.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief usbd core module
* @{
*/
/** @defgroup USBD_AUDIO_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Macros
* @{
*/
#define AUDIO_SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
#define AUDIO_PACKET_SZE(frq) (uint8_t)(((frq * 2 * 2)/1000) & 0xFF), \
(uint8_t)((((frq * 2 * 2)/1000) >> 8) & 0xFF)
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_AUDIO_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_AUDIO_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_AUDIO_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t *USBD_AUDIO_GetCfgDesc (uint16_t *length);
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc (uint16_t *length);
static uint8_t USBD_AUDIO_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_EP0_RxReady (USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_EP0_TxReady (USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_SOF (USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_IsoINIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_IsoOutIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum);
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_AUDIO =
{
USBD_AUDIO_Init,
USBD_AUDIO_DeInit,
USBD_AUDIO_Setup,
USBD_AUDIO_EP0_TxReady,
USBD_AUDIO_EP0_RxReady,
USBD_AUDIO_DataIn,
USBD_AUDIO_DataOut,
USBD_AUDIO_SOF,
USBD_AUDIO_IsoINIncomplete,
USBD_AUDIO_IsoOutIncomplete,
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetCfgDesc,
USBD_AUDIO_GetDeviceQualifierDesc,
};
/* USB AUDIO device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration 1 */
0x09, /* bLength */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType */
LOBYTE(USB_AUDIO_CONFIG_DESC_SIZ), /* wTotalLength 109 bytes*/
HIBYTE(USB_AUDIO_CONFIG_DESC_SIZ),
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xC0, /* bmAttributes BUS Powred*/
0x32, /* bMaxPower = 100 mA*/
/* 09 byte*/
/* USB Speaker Standard interface descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Class-specific AC Interface Descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */
0x00, /* 1.00 */ /* bcdADC */
0x01,
0x27, /* wTotalLength = 39*/
0x00,
0x01, /* bInCollection */
0x01, /* baInterfaceNr */
/* 09 byte*/
/* USB Speaker Input Terminal Descriptor */
AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */
0x01, /* bTerminalID */
0x01, /* wTerminalType AUDIO_TERMINAL_USB_STREAMING 0x0101 */
0x01,
0x00, /* bAssocTerminal */
0x01, /* bNrChannels */
0x00, /* wChannelConfig 0x0000 Mono */
0x00,
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* 12 byte*/
/* USB Speaker Audio Feature Unit Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */
AUDIO_OUT_STREAMING_CTRL, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
AUDIO_CONTROL_MUTE,// |AUDIO_CONTROL_VOLUME, /* bmaControls(0) */
0, /* bmaControls(1) */
0x00, /* iTerminal */
/* 09 byte*/
/*USB Speaker Output Terminal Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */
0x03, /* bTerminalID */
0x01, /* wTerminalType 0x0301*/
0x03,
0x00, /* bAssocTerminal */
0x02, /* bSourceID */
0x00, /* iTerminal */
/* 09 byte*/
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwith */
/* Interface 1, Alternate Setting 0 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Operational */
/* Interface 1, Alternate Setting 1 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Audio Streaming Interface Descriptor */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x01, /* bTerminalLink */
0x01, /* bDelay */
0x01, /* wFormatTag AUDIO_FORMAT_PCM 0x0001*/
0x00,
/* 07 byte*/
/* USB Speaker Audio Type III Format Interface Descriptor */
0x0B, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_III, /* bFormatType */
0x02, /* bNrChannels */
0x02, /* bSubFrameSize : 2 Bytes per frame (16bits) */
16, /* bBitResolution (16-bits per sample) */
0x01, /* bSamFreqType only one frequency supported */
AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ), /* Audio sampling frequency coded on 3 bytes */
/* 11 byte*/
/* Endpoint 1 - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType */
AUDIO_OUT_EP, /* bEndpointAddress 1 out endpoint*/
USBD_EP_TYPE_ISOC, /* bmAttributes */
AUDIO_PACKET_SZE(USBD_AUDIO_FREQ), /* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* 09 byte*/
/* Endpoint - Audio Streaming Descriptor*/
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x00, /* bmAttributes */
0x00, /* bLockDelayUnits */
0x00, /* wLockDelay */
0x00,
/* 07 byte*/
} ;
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_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_AUDIO_Private_Functions
* @{
*/
/**
* @brief USBD_AUDIO_Init
* Initialize the AUDIO interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_AUDIO_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
USBD_AUDIO_HandleTypeDef *haudio;
/* Open EP OUT */
USBD_LL_OpenEP(pdev,
AUDIO_OUT_EP,
USBD_EP_TYPE_ISOC,
AUDIO_OUT_PACKET);
/* Allocate Audio structure */
pdev->pClassData = USBD_malloc(sizeof (USBD_AUDIO_HandleTypeDef));
if(pdev->pClassData == NULL)
{
return USBD_FAIL;
}
else
{
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
haudio->alt_setting = 0;
haudio->offset = AUDIO_OFFSET_UNKNOWN;
haudio->wr_ptr = 0;
haudio->rd_ptr = 0;
haudio->rd_enable = 0;
/* Initialize the Audio output Hardware layer */
if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->Init(USBD_AUDIO_FREQ, AUDIO_DEFAULT_VOLUME, 0) != USBD_OK)
{
return USBD_FAIL;
}
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(pdev,
AUDIO_OUT_EP,
haudio->buffer,
AUDIO_OUT_PACKET);
}
return USBD_OK;
}
/**
* @brief USBD_AUDIO_Init
* DeInitialize the AUDIO layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_AUDIO_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
/* Open EP OUT */
USBD_LL_CloseEP(pdev,
AUDIO_OUT_EP);
/* DeInit physical Interface components */
if(pdev->pClassData != NULL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->DeInit(0);
USBD_free(pdev->pClassData);
pdev->pClassData = NULL;
}
return USBD_OK;
}
/**
* @brief USBD_AUDIO_Setup
* Handle the AUDIO specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_AUDIO_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
uint16_t len;
uint8_t *pbuf;
uint8_t ret = USBD_OK;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case AUDIO_REQ_GET_CUR:
AUDIO_REQ_GetCurrent(pdev, req);
break;
case AUDIO_REQ_SET_CUR:
AUDIO_REQ_SetCurrent(pdev, req);
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_DESCRIPTOR:
if( (req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE)
{
pbuf = USBD_AUDIO_CfgDesc + 18;
len = MIN(USB_AUDIO_DESC_SIZ , req->wLength);
USBD_CtlSendData (pdev,
pbuf,
len);
}
break;
case USB_REQ_GET_INTERFACE :
USBD_CtlSendData (pdev,
(uint8_t *)&(haudio->alt_setting),
1);
break;
case USB_REQ_SET_INTERFACE :
if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES)
{
haudio->alt_setting = (uint8_t)(req->wValue);
}
else
{
/* Call the error management function (command will be nacked */
USBD_CtlError (pdev, req);
}
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
}
return ret;
}
/**
* @brief USBD_AUDIO_GetCfgDesc
* return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_AUDIO_GetCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_AUDIO_CfgDesc);
return USBD_AUDIO_CfgDesc;
}
/**
* @brief USBD_AUDIO_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
/* Only OUT data are processed */
return USBD_OK;
}
/**
* @brief USBD_AUDIO_EP0_RxReady
* handle EP0 Rx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_EP0_RxReady (USBD_HandleTypeDef *pdev)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
if (haudio->control.cmd == AUDIO_REQ_SET_CUR)
{/* In this driver, to simplify code, only SET_CUR request is managed */
if (haudio->control.unit == AUDIO_OUT_STREAMING_CTRL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->MuteCtl(haudio->control.data[0]);
haudio->control.cmd = 0;
haudio->control.len = 0;
}
}
return USBD_OK;
}
/**
* @brief USBD_AUDIO_EP0_TxReady
* handle EP0 TRx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_EP0_TxReady (USBD_HandleTypeDef *pdev)
{
/* Only OUT control data are processed */
return USBD_OK;
}
/**
* @brief USBD_AUDIO_SOF
* handle SOF event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_AUDIO_SOF (USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief USBD_AUDIO_SOF
* handle SOF event
* @param pdev: device instance
* @retval status
*/
void USBD_AUDIO_Sync (USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset)
{
int8_t shift = 0;
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
haudio->offset = offset;
if(haudio->rd_enable == 1)
{
haudio->rd_ptr += AUDIO_TOTAL_BUF_SIZE/2;
if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE)
{
/* roll back */
haudio->rd_ptr = 0;
}
}
if(haudio->rd_ptr > haudio->wr_ptr)
{
if((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET)
{
shift = -4;
}
else if((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
{
shift = 4;
}
}
else
{
if((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET)
{
shift = 4;
}
else if((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
{
shift = -4;
}
}
if(haudio->offset == AUDIO_OFFSET_FULL)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],
AUDIO_TOTAL_BUF_SIZE/2 - shift,
AUDIO_CMD_PLAY);
haudio->offset = AUDIO_OFFSET_NONE;
}
}
/**
* @brief USBD_AUDIO_IsoINIncomplete
* handle data ISO IN Incomplete event
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_IsoINIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum)
{
return USBD_OK;
}
/**
* @brief USBD_AUDIO_IsoOutIncomplete
* handle data ISO OUT Incomplete event
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_IsoOutIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum)
{
return USBD_OK;
}
/**
* @brief USBD_AUDIO_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_AUDIO_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
if (epnum == AUDIO_OUT_EP)
{
/* Increment the Buffer pointer or roll it back when all buffers are full */
haudio->wr_ptr += AUDIO_OUT_PACKET;
if (haudio->wr_ptr == AUDIO_TOTAL_BUF_SIZE)
{/* All buffers are full: roll back */
haudio->wr_ptr = 0;
if(haudio->offset == AUDIO_OFFSET_UNKNOWN)
{
((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],
AUDIO_TOTAL_BUF_SIZE/2,
AUDIO_CMD_START);
haudio->offset = AUDIO_OFFSET_NONE;
}
}
if(haudio->rd_enable == 0)
{
if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2))
{
haudio->rd_enable = 1;
}
}
/* Prepare Out endpoint to receive next audio packet */
USBD_LL_PrepareReceive(pdev,
AUDIO_OUT_EP,
&haudio->buffer[haudio->wr_ptr],
AUDIO_OUT_PACKET);
}
return USBD_OK;
}
/**
* @brief AUDIO_Req_GetCurrent
* Handles the GET_CUR Audio control request.
* @param pdev: instance
* @param req: setup class request
* @retval status
*/
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
memset(haudio->control.data, 0, 64);
/* Send the current mute state */
USBD_CtlSendData (pdev,
haudio->control.data,
req->wLength);
}
/**
* @brief AUDIO_Req_SetCurrent
* Handles the SET_CUR Audio control request.
* @param pdev: instance
* @param req: setup class request
* @retval status
*/
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_AUDIO_HandleTypeDef *haudio;
haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;
if (req->wLength)
{
/* Prepare the reception of the buffer over EP0 */
USBD_CtlPrepareRx (pdev,
haudio->control.data,
req->wLength);
haudio->control.cmd = AUDIO_REQ_SET_CUR; /* Set the request value */
haudio->control.len = req->wLength; /* Set the request data length */
haudio->control.unit = HIBYTE(req->wIndex); /* Set the request target unit */
}
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc (uint16_t *length)
{
*length = sizeof (USBD_AUDIO_DeviceQualifierDesc);
return USBD_AUDIO_DeviceQualifierDesc;
}
/**
* @brief USBD_AUDIO_RegisterInterface
* @param fops: Audio interface callback
* @retval status
*/
uint8_t USBD_AUDIO_RegisterInterface (USBD_HandleTypeDef *pdev,
USBD_AUDIO_ItfTypeDef *fops)
{
if(fops != NULL)
{
pdev->pUserData= fops;
}
return 0;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,190 @@
/**
******************************************************************************
* @file usbd_cdc_if_template.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Generic media access Layer.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_audio_if_template.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_AUDIO
* @brief usbd core module
* @{
*/
/** @defgroup USBD_AUDIO_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
* @{
*/
static int8_t TEMPLATE_Init (uint32_t AudioFreq, uint32_t Volume, uint32_t options);
static int8_t TEMPLATE_DeInit (uint32_t options);
static int8_t TEMPLATE_AudioCmd (uint8_t* pbuf, uint32_t size, uint8_t cmd);
static int8_t TEMPLATE_VolumeCtl (uint8_t vol);
static int8_t TEMPLATE_MuteCtl (uint8_t cmd);
static int8_t TEMPLATE_PeriodicTC (uint8_t cmd);
static int8_t TEMPLATE_GetState (void);
USBD_AUDIO_ItfTypeDef USBD_AUDIO_Template_fops =
{
TEMPLATE_Init,
TEMPLATE_DeInit,
TEMPLATE_AudioCmd,
TEMPLATE_VolumeCtl,
TEMPLATE_MuteCtl,
TEMPLATE_PeriodicTC,
TEMPLATE_GetState,
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief TEMPLATE_Init
* Initializes the AUDIO media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options)
{
/*
Add your initialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_DeInit
* DeInitializes the AUDIO media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_DeInit(uint32_t options)
{
/*
Add your deinitialization code here
*/
return (0);
}
/**
* @brief TEMPLATE_AudioCmd
* AUDIO command handler
* @param Buf: Buffer of data to be sent
* @param size: Number of data to be sent (in bytes)
* @param cmd: command opcode
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_AudioCmd (uint8_t* pbuf, uint32_t size, uint8_t cmd)
{
return (0);
}
/**
* @brief TEMPLATE_VolumeCtl
* @param vol: volume level (0..100)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_VolumeCtl (uint8_t vol)
{
return (0);
}
/**
* @brief TEMPLATE_MuteCtl
* @param cmd: vmute command
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_MuteCtl (uint8_t cmd)
{
return (0);
}
/**
* @brief TEMPLATE_PeriodicTC
* @param cmd
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_PeriodicTC (uint8_t cmd)
{
return (0);
}
/**
* @brief TEMPLATE_GetState
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t TEMPLATE_GetState (void)
{
return (0);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,169 @@
/**
******************************************************************************
* @file usbd_conf_template.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Header file for the usbd_conf_template.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF_TEMPLATE_H
#define __USBD_CONF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32fxxx.h" /* replace 'stm32xxx' with your HAL driver header filename, ex: stm32f4xx.h */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CONF
* @brief USB device low level driver configuration file
* @{
*/
/** @defgroup USBD_CONF_Exported_Defines
* @{
*/
#define USBD_MAX_NUM_INTERFACES 1
#define USBD_MAX_NUM_CONFIGURATION 1
#define USBD_MAX_STR_DESC_SIZ 0x100
#define USBD_SUPPORT_USER_STRING 0
#define USBD_SELF_POWERED 1
#define USBD_DEBUG_LEVEL 2
/* MSC Class Config */
#define MSC_MEDIA_PACKET 8192
/* CDC Class Config */
#define USBD_CDC_INTERVAL 2000
/* DFU Class Config */
#define USBD_DFU_MAX_ITF_NUM 1
#define USBD_DFU_XFERS_IZE 1024
/* AUDIO Class Config */
#define USBD_AUDIO_FREQ 22100
/** @defgroup USBD_Exported_Macros
* @{
*/
/* Memory management macros */
#define USBD_malloc malloc
#define USBD_free free
#define USBD_memset memset
#define USBD_memcpy memcpy
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_UsrLog(...)
#endif
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) printf("ERROR: ") ;\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_ErrLog(...)
#endif
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) printf("DEBUG : ") ;\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBD_DbgLog(...)
#endif
/**
* @}
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF_TEMPLATE_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,167 @@
/**
******************************************************************************
* @file usbd_core.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Header file for usbd_core.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CORE_H
#define __USBD_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
#include "usbd_def.h"
#include "usbd_ioreq.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CORE
* @brief This file is the Header file for usbd_core.c file
* @{
*/
/** @defgroup USBD_CORE_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
#define USBD_SOF USBD_LL_SOF
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
/* USBD Low Level Driver */
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t ep_type,
uint16_t ep_mps);
USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr);
USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t size);
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t size);
uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
void USBD_LL_Delay (uint32_t Delay);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CORE_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,113 @@
/**
******************************************************************************
* @file usbd_req.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Header file for the usbd_req.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_REQUEST_H
#define __USB_REQUEST_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_REQ
* @brief header file for the usbd_req.c file
* @{
*/
/** @defgroup USBD_REQ_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata);
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_REQUEST_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,330 @@
/**
******************************************************************************
* @file usbd_def.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief General defines for the usb device library
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DEF_H
#define __USBD_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
/** @addtogroup STM32_USBD_DEVICE_LIBRARY
* @{
*/
/** @defgroup USB_DEF
* @brief general defines for the usb device library file
* @{
*/
/** @defgroup USB_DEF_Exported_Defines
* @{
*/
#ifndef NULL
#define NULL 0
#endif
#define USB_LEN_DEV_QUALIFIER_DESC 0x0A
#define USB_LEN_DEV_DESC 0x12
#define USB_LEN_CFG_DESC 0x09
#define USB_LEN_IF_DESC 0x09
#define USB_LEN_EP_DESC 0x07
#define USB_LEN_OTG_DESC 0x03
#define USB_LEN_LANGID_STR_DESC 0x04
#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09
#define USBD_IDX_LANGID_STR 0x00
#define USBD_IDX_MFC_STR 0x01
#define USBD_IDX_PRODUCT_STR 0x02
#define USBD_IDX_SERIAL_STR 0x03
#define USBD_IDX_CONFIG_STR 0x04
#define USBD_IDX_INTERFACE_STR 0x05
#define USB_REQ_TYPE_STANDARD 0x00
#define USB_REQ_TYPE_CLASS 0x20
#define USB_REQ_TYPE_VENDOR 0x40
#define USB_REQ_TYPE_MASK 0x60
#define USB_REQ_RECIPIENT_DEVICE 0x00
#define USB_REQ_RECIPIENT_INTERFACE 0x01
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
#define USB_REQ_RECIPIENT_MASK 0x03
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
#define USB_DESC_TYPE_BOS 0x0F
#define USB_CONFIG_REMOTE_WAKEUP 2
#define USB_CONFIG_SELF_POWERED 1
#define USB_FEATURE_EP_HALT 0
#define USB_FEATURE_REMOTE_WAKEUP 1
#define USB_FEATURE_TEST_MODE 2
#define USB_DEVICE_CAPABITY_TYPE 0x10
#define USB_HS_MAX_PACKET_SIZE 512
#define USB_FS_MAX_PACKET_SIZE 64
#define USB_MAX_EP0_SIZE 64
/* Device Status */
#define USBD_STATE_DEFAULT 1
#define USBD_STATE_ADDRESSED 2
#define USBD_STATE_CONFIGURED 3
#define USBD_STATE_SUSPENDED 4
/* EP0 State */
#define USBD_EP0_IDLE 0
#define USBD_EP0_SETUP 1
#define USBD_EP0_DATA_IN 2
#define USBD_EP0_DATA_OUT 3
#define USBD_EP0_STATUS_IN 4
#define USBD_EP0_STATUS_OUT 5
#define USBD_EP0_STALL 6
#define USBD_EP_TYPE_CTRL 0
#define USBD_EP_TYPE_ISOC 1
#define USBD_EP_TYPE_BULK 2
#define USBD_EP_TYPE_INTR 3
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_TypesDefinitions
* @{
*/
typedef struct usb_setup_req
{
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
}USBD_SetupReqTypedef;
struct _USBD_HandleTypeDef;
typedef struct _Device_cb
{
uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
/* Control Endpoints*/
uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req);
uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev );
uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev );
/* Class Specific Endpoints*/
uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev);
uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING == 1)
uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length);
#endif
} USBD_ClassTypeDef;
/* Following USB Device Speed */
typedef enum
{
USBD_SPEED_HIGH = 0,
USBD_SPEED_FULL = 1,
USBD_SPEED_LOW = 2,
}USBD_SpeedTypeDef;
/* Following USB Device status */
typedef enum {
USBD_OK = 0,
USBD_BUSY,
USBD_FAIL,
}USBD_StatusTypeDef;
/* USB Device descriptors structure */
typedef struct
{
uint8_t *(*GetDeviceDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetLangIDStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetManufacturerStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetProductStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetSerialStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetConfigurationStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetInterfaceStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *(*GetBOSDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
#endif
} USBD_DescriptorsTypeDef;
/* USB Device handle structure */
typedef struct
{
uint32_t status;
uint32_t total_length;
uint32_t rem_length;
uint32_t maxpacket;
} USBD_EndpointTypeDef;
/* USB Device handle structure */
typedef struct _USBD_HandleTypeDef
{
uint8_t id;
uint32_t dev_config;
uint32_t dev_default_config;
uint32_t dev_config_status;
USBD_SpeedTypeDef dev_speed;
USBD_EndpointTypeDef ep_in[15];
USBD_EndpointTypeDef ep_out[15];
uint32_t ep0_state;
uint32_t ep0_data_len;
uint8_t dev_state;
uint8_t dev_old_state;
uint8_t dev_address;
uint8_t dev_connection_status;
uint8_t dev_test_mode;
uint32_t dev_remote_wakeup;
USBD_SetupReqTypedef request;
USBD_DescriptorsTypeDef *pDesc;
USBD_ClassTypeDef *pClass;
void *pClassData;
void *pUserData;
void *pData;
} USBD_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_Macros
* @{
*/
#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
(((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))
#endif /* __weak */
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif /* __packed */
#endif /* __GNUC__ */
/* In HS mode and when the DMA is used, all variables and data structures dealing
with the DMA during the transaction process should be 4-bytes aligned */
#if defined (__GNUC__) /* GNU Compiler */
#define __ALIGN_END __attribute__ ((aligned (4)))
#define __ALIGN_BEGIN
#else
#define __ALIGN_END
#if defined (__CC_ARM) /* ARM Compiler */
#define __ALIGN_BEGIN __align(4)
#elif defined (__ICCARM__) /* IAR Compiler */
#define __ALIGN_BEGIN
#elif defined (__TASKING__) /* TASKING Compiler */
#define __ALIGN_BEGIN __align(4)
#endif /* __CC_ARM */
#endif /* __GNUC__ */
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DEF_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,128 @@
/**
******************************************************************************
* @file usbd_ioreq.h
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief Header file for the usbd_ioreq.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_IOREQ_H
#define __USBD_IOREQ_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
#include "usbd_core.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_IOREQ
* @brief header file for the usbd_ioreq.c file
* @{
*/
/** @defgroup USBD_IOREQ_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
uint8_t *buf,
uint16_t len);
USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len);
USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len);
USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len);
USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev);
uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev ,
uint8_t epnum);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_IOREQ_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,212 @@
/**
******************************************************************************
* @file usbd_conf_template.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief USB Device configuration and interface file
* This template should be copied to the user folder, renamed and customized
* following user needs.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_core.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the Low Level portion of the Device driver.
* @param pdev: Device handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief De-Initializes the Low Level portion of the Device driver.
* @param pdev: Device handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief Starts the Low Level portion of the Device driver.
* @param pdev: Device handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief Stops the Low Level portion of the Device driver.
* @param pdev: Device handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief Opens an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @param ep_type: Endpoint Type
* @param ep_mps: Endpoint Max Packet Size
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t ep_type,
uint16_t ep_mps)
{
return USBD_OK;
}
/**
* @brief Closes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_OK;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_OK;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_OK;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_OK;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return 0;
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
return USBD_OK;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t size)
{
return USBD_OK;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t size)
{
return USBD_OK;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint Number
* @retval Recived Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return 0;
}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay)
{
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,565 @@
/**
******************************************************************************
* @file usbd_core.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief This file provides all the USBD core functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_core.h"
/** @addtogroup STM32_USBD_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CORE
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Private_Functions
* @{
*/
/**
* @brief USBD_Init
* Initializes the device stack and load the class driver
* @param pdev: device instance
* @param pdesc: Descriptor structure address
* @param id: Low level core index
* @retval None
*/
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id)
{
/* Check whether the USB Host handle is valid */
if(pdev == NULL)
{
USBD_ErrLog("Invalid Device handle");
return USBD_FAIL;
}
/* Unlink previous class*/
if(pdev->pClass != NULL)
{
pdev->pClass = NULL;
}
/* Assign USBD Descriptors */
if(pdesc != NULL)
{
pdev->pDesc = pdesc;
}
/* Set Device initial State */
pdev->dev_state = USBD_STATE_DEFAULT;
pdev->id = id;
/* Initialize low level driver */
USBD_LL_Init(pdev);
return USBD_OK;
}
/**
* @brief USBD_DeInit
* Re-Initialize th device library
* @param pdev: device instance
* @retval status: status
*/
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
{
/* Set Default State */
pdev->dev_state = USBD_STATE_DEFAULT;
/* Free Class Resources */
pdev->pClass->DeInit(pdev, pdev->dev_config);
/* Stop the low level driver */
USBD_LL_Stop(pdev);
/* Initialize low level driver */
USBD_LL_DeInit(pdev);
return USBD_OK;
}
/**
* @brief USBD_RegisterClass
* Link class driver to Device Core.
* @param pDevice : Device Handle
* @param pclass: Class handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
{
USBD_StatusTypeDef status = USBD_OK;
if(pclass != 0)
{
/* link the class to the USB Device handle */
pdev->pClass = pclass;
status = USBD_OK;
}
else
{
USBD_ErrLog("Invalid Class handle");
status = USBD_FAIL;
}
return status;
}
/**
* @brief USBD_Start
* Start the USB Device Core.
* @param pdev: Device Handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev)
{
/* Start the low level driver */
USBD_LL_Start(pdev);
return USBD_OK;
}
/**
* @brief USBD_Stop
* Stop the USB Device Core.
* @param pdev: Device Handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev)
{
/* Free Class Resources */
pdev->pClass->DeInit(pdev, pdev->dev_config);
/* Stop the low level driver */
USBD_LL_Stop(pdev);
return USBD_OK;
}
/**
* @brief USBD_RunTestMode
* Launch test mode process
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief USBD_SetClassConfig
* Configure device and start the interface
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
USBD_StatusTypeDef ret = USBD_FAIL;
if(pdev->pClass != NULL)
{
/* Set configuration and Start the Class*/
if(pdev->pClass->Init(pdev, cfgidx) == 0)
{
ret = USBD_OK;
}
}
return ret;
}
/**
* @brief USBD_ClrClassConfig
* Clear current configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status: USBD_StatusTypeDef
*/
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/* Clear configuration and De-initialize the Class process*/
pdev->pClass->DeInit(pdev, cfgidx);
return USBD_OK;
}
/**
* @brief USBD_SetupStage
* Handle the setup stage
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
{
USBD_ParseSetupRequest(&pdev->request, psetup);
pdev->ep0_state = USBD_EP0_SETUP;
pdev->ep0_data_len = pdev->request.wLength;
switch (pdev->request.bmRequest & 0x1F)
{
case USB_REQ_RECIPIENT_DEVICE:
USBD_StdDevReq (pdev, &pdev->request);
break;
case USB_REQ_RECIPIENT_INTERFACE:
USBD_StdItfReq(pdev, &pdev->request);
break;
case USB_REQ_RECIPIENT_ENDPOINT:
USBD_StdEPReq(pdev, &pdev->request);
break;
default:
USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80);
break;
}
return USBD_OK;
}
/**
* @brief USBD_DataOutStage
* Handle data OUT stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata)
{
USBD_EndpointTypeDef *pep;
if(epnum == 0)
{
pep = &pdev->ep_out[0];
if ( pdev->ep0_state == USBD_EP0_DATA_OUT)
{
if(pep->rem_length > pep->maxpacket)
{
pep->rem_length -= pep->maxpacket;
USBD_CtlContinueRx (pdev,
pdata,
MIN(pep->rem_length ,pep->maxpacket));
}
else
{
if((pdev->pClass->EP0_RxReady != NULL)&&
(pdev->dev_state == USBD_STATE_CONFIGURED))
{
pdev->pClass->EP0_RxReady(pdev);
}
USBD_CtlSendStatus(pdev);
}
}
}
else if((pdev->pClass->DataOut != NULL)&&
(pdev->dev_state == USBD_STATE_CONFIGURED))
{
pdev->pClass->DataOut(pdev, epnum);
}
return USBD_OK;
}
/**
* @brief USBD_DataInStage
* Handle data in stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata)
{
USBD_EndpointTypeDef *pep;
if(epnum == 0)
{
pep = &pdev->ep_in[0];
if ( pdev->ep0_state == USBD_EP0_DATA_IN)
{
if(pep->rem_length > pep->maxpacket)
{
pep->rem_length -= pep->maxpacket;
USBD_CtlContinueSendData (pdev,
pdata,
pep->rem_length);
/* Prepare endpoint for premature end of transfer */
USBD_LL_PrepareReceive (pdev,
0,
NULL,
0);
}
else
{ /* last packet is MPS multiple, so send ZLP packet */
if((pep->total_length % pep->maxpacket == 0) &&
(pep->total_length >= pep->maxpacket) &&
(pep->total_length < pdev->ep0_data_len ))
{
USBD_CtlContinueSendData(pdev , NULL, 0);
pdev->ep0_data_len = 0;
/* Prepare endpoint for premature end of transfer */
USBD_LL_PrepareReceive (pdev,
0,
NULL,
0);
}
else
{
if((pdev->pClass->EP0_TxSent != NULL)&&
(pdev->dev_state == USBD_STATE_CONFIGURED))
{
pdev->pClass->EP0_TxSent(pdev);
}
USBD_CtlReceiveStatus(pdev);
}
}
}
if (pdev->dev_test_mode == 1)
{
USBD_RunTestMode(pdev);
pdev->dev_test_mode = 0;
}
}
else if((pdev->pClass->DataIn != NULL)&&
(pdev->dev_state == USBD_STATE_CONFIGURED))
{
pdev->pClass->DataIn(pdev, epnum);
}
return USBD_OK;
}
/**
* @brief USBD_LL_Reset
* Handle Reset event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
{
/* Open EP0 OUT */
USBD_LL_OpenEP(pdev,
0x00,
USBD_EP_TYPE_CTRL,
USB_MAX_EP0_SIZE);
pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
/* Open EP0 IN */
USBD_LL_OpenEP(pdev,
0x80,
USBD_EP_TYPE_CTRL,
USB_MAX_EP0_SIZE);
pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
/* Upon Reset call user call back */
pdev->dev_state = USBD_STATE_DEFAULT;
if (pdev->pClassData)
pdev->pClass->DeInit(pdev, pdev->dev_config);
return USBD_OK;
}
/**
* @brief USBD_LL_Reset
* Handle Reset event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed)
{
pdev->dev_speed = speed;
return USBD_OK;
}
/**
* @brief USBD_Suspend
* Handle Suspend event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
{
pdev->dev_old_state = pdev->dev_state;
pdev->dev_state = USBD_STATE_SUSPENDED;
return USBD_OK;
}
/**
* @brief USBD_Resume
* Handle Resume event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
{
pdev->dev_state = pdev->dev_old_state;
return USBD_OK;
}
/**
* @brief USBD_SOF
* Handle SOF event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
{
if(pdev->dev_state == USBD_STATE_CONFIGURED)
{
if(pdev->pClass->SOF != NULL)
{
pdev->pClass->SOF(pdev);
}
}
return USBD_OK;
}
/**
* @brief USBD_IsoINIncomplete
* Handle iso in incomplete event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
return USBD_OK;
}
/**
* @brief USBD_IsoOUTIncomplete
* Handle iso out incomplete event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
return USBD_OK;
}
/**
* @brief USBD_DevConnected
* Handle device connection event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
{
return USBD_OK;
}
/**
* @brief USBD_DevDisconnected
* Handle device disconnection event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
{
/* Free Class Resources */
pdev->dev_state = USBD_STATE_DEFAULT;
pdev->pClass->DeInit(pdev, pdev->dev_config);
return USBD_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,782 @@
/**
******************************************************************************
* @file usbd_req.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief This file provides the standard USB requests following chapter 9.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_ctlreq.h"
#include "usbd_ioreq.h"
/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_REQ
* @brief USB standard requests module
* @{
*/
/** @defgroup USBD_REQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_REQ_Private_FunctionPrototypes
* @{
*/
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req);
static uint8_t USBD_GetLen(uint8_t *buf);
/**
* @}
*/
/** @defgroup USBD_REQ_Private_Functions
* @{
*/
/**
* @brief USBD_StdDevReq
* Handle standard usb device requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
switch (req->bRequest)
{
case USB_REQ_GET_DESCRIPTOR:
USBD_GetDescriptor (pdev, req) ;
break;
case USB_REQ_SET_ADDRESS:
USBD_SetAddress(pdev, req);
break;
case USB_REQ_SET_CONFIGURATION:
USBD_SetConfig (pdev , req);
break;
case USB_REQ_GET_CONFIGURATION:
USBD_GetConfig (pdev , req);
break;
case USB_REQ_GET_STATUS:
USBD_GetStatus (pdev , req);
break;
case USB_REQ_SET_FEATURE:
USBD_SetFeature (pdev , req);
break;
case USB_REQ_CLEAR_FEATURE:
USBD_ClrFeature (pdev , req);
break;
default:
USBD_CtlError(pdev , req);
break;
}
return ret;
}
/**
* @brief USBD_StdItfReq
* Handle standard usb interface requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
switch (pdev->dev_state)
{
case USBD_STATE_CONFIGURED:
if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
{
pdev->pClass->Setup (pdev, req);
if((req->wLength == 0)&& (ret == USBD_OK))
{
USBD_CtlSendStatus(pdev);
}
}
else
{
USBD_CtlError(pdev , req);
}
break;
default:
USBD_CtlError(pdev , req);
break;
}
return USBD_OK;
}
/**
* @brief USBD_StdEPReq
* Handle standard usb endpoint requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
{
uint8_t ep_addr;
USBD_StatusTypeDef ret = USBD_OK;
USBD_EndpointTypeDef *pep;
ep_addr = LOBYTE(req->wIndex);
/* Check if it is a class request */
if ((req->bmRequest & 0x60) == 0x20)
{
pdev->pClass->Setup (pdev, req);
return USBD_OK;
}
switch (req->bRequest)
{
case USB_REQ_SET_FEATURE :
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
if ((ep_addr != 0x00) && (ep_addr != 0x80))
{
USBD_LL_StallEP(pdev , ep_addr);
}
break;
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_EP_HALT)
{
if ((ep_addr != 0x00) && (ep_addr != 0x80))
{
USBD_LL_StallEP(pdev , ep_addr);
}
}
pdev->pClass->Setup (pdev, req);
USBD_CtlSendStatus(pdev);
break;
default:
USBD_CtlError(pdev , req);
break;
}
break;
case USB_REQ_CLEAR_FEATURE :
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
if ((ep_addr != 0x00) && (ep_addr != 0x80))
{
USBD_LL_StallEP(pdev , ep_addr);
}
break;
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_EP_HALT)
{
if ((ep_addr & 0x7F) != 0x00)
{
USBD_LL_ClearStallEP(pdev , ep_addr);
pdev->pClass->Setup (pdev, req);
}
USBD_CtlSendStatus(pdev);
}
break;
default:
USBD_CtlError(pdev , req);
break;
}
break;
case USB_REQ_GET_STATUS:
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
if ((ep_addr & 0x7F) != 0x00)
{
USBD_LL_StallEP(pdev , ep_addr);
}
break;
case USBD_STATE_CONFIGURED:
pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\
&pdev->ep_out[ep_addr & 0x7F];
if(USBD_LL_IsStallEP(pdev, ep_addr))
{
pep->status = 0x0001;
}
else
{
pep->status = 0x0000;
}
USBD_CtlSendData (pdev,
(uint8_t *)&pep->status,
2);
break;
default:
USBD_CtlError(pdev , req);
break;
}
break;
default:
break;
}
return ret;
}
/**
* @brief USBD_GetDescriptor
* Handle Get Descriptor requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
uint16_t len;
uint8_t *pbuf;
switch (req->wValue >> 8)
{
#if (USBD_LPM_ENABLED == 1)
case USB_DESC_TYPE_BOS:
pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
break;
#endif
case USB_DESC_TYPE_DEVICE:
pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
break;
case USB_DESC_TYPE_CONFIGURATION:
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len);
pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
}
else
{
pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len);
pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
}
break;
case USB_DESC_TYPE_STRING:
switch ((uint8_t)(req->wValue))
{
case USBD_IDX_LANGID_STR:
pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
break;
case USBD_IDX_MFC_STR:
pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
break;
case USBD_IDX_PRODUCT_STR:
pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
break;
case USBD_IDX_SERIAL_STR:
pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
break;
case USBD_IDX_CONFIG_STR:
pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
break;
case USBD_IDX_INTERFACE_STR:
pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
break;
default:
#if (USBD_SUPPORT_USER_STRING == 1)
pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len);
break;
#else
USBD_CtlError(pdev , req);
return;
#endif
}
break;
case USB_DESC_TYPE_DEVICE_QUALIFIER:
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len);
break;
}
else
{
USBD_CtlError(pdev , req);
return;
}
case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len);
pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
break;
}
else
{
USBD_CtlError(pdev , req);
return;
}
default:
USBD_CtlError(pdev , req);
return;
}
if((len != 0)&& (req->wLength != 0))
{
len = MIN(len , req->wLength);
USBD_CtlSendData (pdev,
pbuf,
len);
}
}
/**
* @brief USBD_SetAddress
* Set device address
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
uint8_t dev_addr;
if ((req->wIndex == 0) && (req->wLength == 0))
{
dev_addr = (uint8_t)(req->wValue) & 0x7F;
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlError(pdev , req);
}
else
{
pdev->dev_address = dev_addr;
USBD_LL_SetUSBAddress(pdev, dev_addr);
USBD_CtlSendStatus(pdev);
if (dev_addr != 0)
{
pdev->dev_state = USBD_STATE_ADDRESSED;
}
else
{
pdev->dev_state = USBD_STATE_DEFAULT;
}
}
}
else
{
USBD_CtlError(pdev , req);
}
}
/**
* @brief USBD_SetConfig
* Handle Set device configuration request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
static uint8_t cfgidx;
cfgidx = (uint8_t)(req->wValue);
if (cfgidx > USBD_MAX_NUM_CONFIGURATION )
{
USBD_CtlError(pdev , req);
}
else
{
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
if (cfgidx)
{
pdev->dev_config = cfgidx;
pdev->dev_state = USBD_STATE_CONFIGURED;
if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
{
USBD_CtlError(pdev , req);
return;
}
USBD_CtlSendStatus(pdev);
}
else
{
USBD_CtlSendStatus(pdev);
}
break;
case USBD_STATE_CONFIGURED:
if (cfgidx == 0)
{
pdev->dev_state = USBD_STATE_ADDRESSED;
pdev->dev_config = cfgidx;
USBD_ClrClassConfig(pdev , cfgidx);
USBD_CtlSendStatus(pdev);
}
else if (cfgidx != pdev->dev_config)
{
/* Clear old configuration */
USBD_ClrClassConfig(pdev , pdev->dev_config);
/* set new configuration */
pdev->dev_config = cfgidx;
if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
{
USBD_CtlError(pdev , req);
return;
}
USBD_CtlSendStatus(pdev);
}
else
{
USBD_CtlSendStatus(pdev);
}
break;
default:
USBD_CtlError(pdev , req);
break;
}
}
}
/**
* @brief USBD_GetConfig
* Handle Get device configuration request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
if (req->wLength != 1)
{
USBD_CtlError(pdev , req);
}
else
{
switch (pdev->dev_state )
{
case USBD_STATE_ADDRESSED:
pdev->dev_default_config = 0;
USBD_CtlSendData (pdev,
(uint8_t *)&pdev->dev_default_config,
1);
break;
case USBD_STATE_CONFIGURED:
USBD_CtlSendData (pdev,
(uint8_t *)&pdev->dev_config,
1);
break;
default:
USBD_CtlError(pdev , req);
break;
}
}
}
/**
* @brief USBD_GetStatus
* Handle Get Status request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
case USBD_STATE_CONFIGURED:
#if ( USBD_SELF_POWERED == 1)
pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
#else
pdev->dev_config_status = 0;
#endif
if (pdev->dev_remote_wakeup)
{
pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
}
USBD_CtlSendData (pdev,
(uint8_t *)& pdev->dev_config_status,
2);
break;
default :
USBD_CtlError(pdev , req);
break;
}
}
/**
* @brief USBD_SetFeature
* Handle Set device feature request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
{
pdev->dev_remote_wakeup = 1;
pdev->pClass->Setup (pdev, req);
USBD_CtlSendStatus(pdev);
}
}
/**
* @brief USBD_ClrFeature
* Handle clear device feature request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
switch (pdev->dev_state)
{
case USBD_STATE_ADDRESSED:
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
{
pdev->dev_remote_wakeup = 0;
pdev->pClass->Setup (pdev, req);
USBD_CtlSendStatus(pdev);
}
break;
default :
USBD_CtlError(pdev , req);
break;
}
}
/**
* @brief USBD_ParseSetupRequest
* Copy buffer into setup structure
* @param pdev: device instance
* @param req: usb request
* @retval None
*/
void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
{
req->bmRequest = *(uint8_t *) (pdata);
req->bRequest = *(uint8_t *) (pdata + 1);
req->wValue = SWAPBYTE (pdata + 2);
req->wIndex = SWAPBYTE (pdata + 4);
req->wLength = SWAPBYTE (pdata + 6);
}
/**
* @brief USBD_CtlError
* Handle USB low level Error
* @param pdev: device instance
* @param req: usb request
* @retval None
*/
void USBD_CtlError( USBD_HandleTypeDef *pdev ,
USBD_SetupReqTypedef *req)
{
USBD_LL_StallEP(pdev , 0x80);
USBD_LL_StallEP(pdev , 0);
}
/**
* @brief USBD_GetString
* Convert Ascii string into unicode one
* @param desc : descriptor buffer
* @param unicode : Formatted string buffer (unicode)
* @param len : descriptor length
* @retval None
*/
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
{
uint8_t idx = 0;
if (desc != NULL)
{
*len = USBD_GetLen(desc) * 2 + 2;
unicode[idx++] = *len;
unicode[idx++] = USB_DESC_TYPE_STRING;
while (*desc != '\0')
{
unicode[idx++] = *desc++;
unicode[idx++] = 0x00;
}
}
}
/**
* @brief USBD_GetLen
* return the string length
* @param buf : pointer to the ascii string buffer
* @retval string length
*/
static uint8_t USBD_GetLen(uint8_t *buf)
{
uint8_t len = 0;
while (*buf != '\0')
{
len++;
buf++;
}
return len;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,236 @@
/**
******************************************************************************
* @file usbd_ioreq.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief This file provides the IO requests APIs for control endpoints.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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 "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_IOREQ
* @brief control I/O requests module
* @{
*/
/** @defgroup USBD_IOREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBD_IOREQ_Private_Functions
* @{
*/
/**
* @brief USBD_CtlSendData
* send data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_IN;
pdev->ep_in[0].total_length = len;
pdev->ep_in[0].rem_length = len;
/* Start the transfer */
USBD_LL_Transmit (pdev, 0x00, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueSendData
* continue sending data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len)
{
/* Start the next transfer */
USBD_LL_Transmit (pdev, 0x00, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlPrepareRx
* receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_OUT;
pdev->ep_out[0].total_length = len;
pdev->ep_out[0].rem_length = len;
/* Start the transfer */
USBD_LL_PrepareReceive (pdev,
0,
pbuf,
len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueRx
* continue receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t len)
{
USBD_LL_PrepareReceive (pdev,
0,
pbuf,
len);
return USBD_OK;
}
/**
* @brief USBD_CtlSendStatus
* send zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_IN;
/* Start the transfer */
USBD_LL_Transmit (pdev, 0x00, NULL, 0);
return USBD_OK;
}
/**
* @brief USBD_CtlReceiveStatus
* receive zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_OUT;
/* Start the transfer */
USBD_LL_PrepareReceive ( pdev,
0,
NULL,
0);
return USBD_OK;
}
/**
* @brief USBD_GetRxCount
* returns the received data length
* @param pdev: device instance
* @param ep_addr: endpoint address
* @retval Rx Data blength
*/
uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr)
{
return USBD_LL_GetRxDataSize(pdev, ep_addr);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,233 @@
/**
******************************************************************************
* @file usbh_msc.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file contains all the prototypes for the usbh_msc.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_H
#define __USBH_MSC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_msc_bot.h"
#include "usbh_msc_scsi.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file is the Header file for usbh_msc.c
* @{
*/
/** @defgroup USBH_MSC_CORE_Exported_Types
* @{
*/
typedef enum
{
MSC_INIT = 0,
MSC_IDLE,
MSC_TEST_UNIT_READY,
MSC_READ_CAPACITY10,
MSC_READ_INQUIRY,
MSC_REQUEST_SENSE,
MSC_READ,
MSC_WRITE,
MSC_UNRECOVERED_ERROR,
MSC_PERIODIC_CHECK,
}
MSC_StateTypeDef;
typedef enum
{
MSC_OK,
MSC_NOT_READY,
MSC_ERROR,
}
MSC_ErrorTypeDef;
typedef enum
{
MSC_REQ_IDLE = 0,
MSC_REQ_RESET,
MSC_REQ_GET_MAX_LUN,
MSC_REQ_ERROR,
}
MSC_ReqStateTypeDef;
#ifndef MAX_SUPPORTED_LUN
#define MAX_SUPPORTED_LUN 2
#endif
/* Structure for LUN */
typedef struct
{
MSC_StateTypeDef state;
MSC_ErrorTypeDef error;
USBH_StatusTypeDef prev_ready_state;
SCSI_CapacityTypeDef capacity;
SCSI_SenseTypeDef sense;
SCSI_StdInquiryDataTypeDef inquiry;
uint8_t state_changed;
}
MSC_LUNTypeDef;
/* Structure for MSC process */
typedef struct _MSC_Process
{
uint32_t max_lun;
uint8_t InPipe;
uint8_t OutPipe;
uint8_t OutEp;
uint8_t InEp;
uint16_t OutEpSize;
uint16_t InEpSize;
MSC_StateTypeDef state;
MSC_ErrorTypeDef error;
MSC_ReqStateTypeDef req_state;
MSC_ReqStateTypeDef prev_req_state;
BOT_HandleTypeDef hbot;
MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN];
uint16_t current_lun;
uint16_t rw_lun;
uint32_t timer;
}
MSC_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Defines
* @{
*/
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
/* MSC Class Codes */
#define USB_MSC_CLASS 0x08
/* Interface Descriptor field values for HID Boot Protocol */
#define MSC_BOT 0x50
#define MSC_TRANSPARENT 0x06
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
extern USBH_ClassTypeDef USBH_msc;
#define USBH_MSC_CLASS &USBH_msc
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype
* @{
*/
/* Common APIs */
uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost);
/* APIs for LUN */
int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost);
uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun);
USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info);
USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_MSC_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,241 @@
/**
******************************************************************************
* @file usbh_msc_bot.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_msc_bot.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_BOT_H
#define __USBH_MSC_BOT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_msc_bot.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file is the Header file for usbh_msc_bot.c
* @{
*/
/** @defgroup USBH_MSC_BOT_Exported_Types
* @{
*/
typedef enum {
BOT_OK = 0,
BOT_FAIL = 1,
BOT_PHASE_ERROR = 2,
BOT_BUSY = 3
}
BOT_StatusTypeDef;
typedef enum {
BOT_CMD_IDLE = 0,
BOT_CMD_SEND,
BOT_CMD_WAIT,
}
BOT_CMDStateTypeDef;
/* CSW Status Definitions */
typedef enum
{
BOT_CSW_CMD_PASSED = 0x00,
BOT_CSW_CMD_FAILED = 0x01,
BOT_CSW_PHASE_ERROR = 0x02,
}
BOT_CSWStatusTypeDef;
typedef enum {
BOT_SEND_CBW = 1,
BOT_SEND_CBW_WAIT,
BOT_DATA_IN,
BOT_DATA_IN_WAIT,
BOT_DATA_OUT,
BOT_DATA_OUT_WAIT,
BOT_RECEIVE_CSW,
BOT_RECEIVE_CSW_WAIT,
BOT_ERROR_IN,
BOT_ERROR_OUT,
BOT_UNRECOVERED_ERROR
}
BOT_StateTypeDef;
typedef union
{
struct __CBW
{
uint32_t Signature;
uint32_t Tag;
uint32_t DataTransferLength;
uint8_t Flags;
uint8_t LUN;
uint8_t CBLength;
uint8_t CB[16];
}field;
uint8_t data[31];
}
BOT_CBWTypeDef;
typedef union
{
struct __CSW
{
uint32_t Signature;
uint32_t Tag;
uint32_t DataResidue;
uint8_t Status;
}field;
uint8_t data[13];
}
BOT_CSWTypeDef;
typedef struct
{
uint32_t data[16];
BOT_StateTypeDef state;
BOT_StateTypeDef prev_state;
BOT_CMDStateTypeDef cmd_state;
BOT_CBWTypeDef cbw;
uint8_t Reserved1;
BOT_CSWTypeDef csw;
uint8_t Reserved2[3];
uint8_t *pbuf;
}
BOT_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Defines
* @{
*/
#define BOT_CBW_SIGNATURE 0x43425355
#define BOT_CBW_TAG 0x20304050
#define BOT_CSW_SIGNATURE 0x53425355
#define BOT_CBW_LENGTH 31
#define BOT_CSW_LENGTH 13
#define BOT_SEND_CSW_DISABLE 0
#define BOT_SEND_CSW_ENABLE 1
#define BOT_DIR_IN 0
#define BOT_DIR_OUT 1
#define BOT_DIR_BOTH 2
#define BOT_PAGE_LENGTH 512
#define BOT_CBW_CB_LENGTH 16
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
#define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk
Endpoint continuously, this means
that device and Host has phase error
Hence a Reset is needed */
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun);
USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun);
USBH_StatusTypeDef USBH_MSC_BOT_Error(USBH_HandleTypeDef *phost, uint8_t lun);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_MSC_BOT_H__ */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,226 @@
/**
******************************************************************************
* @file usbh_msc_scsi.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_msc_scsi.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_SCSI_H
#define __USBH_MSC_SCSI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file is the Header file for usbh_msc_scsi.c
* @{
*/
// Capacity data.
typedef struct
{
uint32_t block_nbr;
uint16_t block_size;
} SCSI_CapacityTypeDef;
// Sense data.
typedef struct
{
uint8_t key;
uint8_t asc;
uint8_t ascq;
} SCSI_SenseTypeDef;
// INQUIRY data.
typedef struct
{
uint8_t PeripheralQualifier;
uint8_t DeviceType;
uint8_t RemovableMedia;
uint8_t vendor_id[9];
uint8_t product_id[17];
uint8_t revision_id[5];
}SCSI_StdInquiryDataTypeDef;
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define OPCODE_TEST_UNIT_READY 0x00
#define OPCODE_READ_CAPACITY10 0x25
#define OPCODE_READ10 0x28
#define OPCODE_WRITE10 0x2A
#define OPCODE_REQUEST_SENSE 0x03
#define OPCODE_INQUIRY 0x12
#define DATA_LEN_MODE_TEST_UNIT_READY 0
#define DATA_LEN_READ_CAPACITY10 8
#define DATA_LEN_INQUIRY 36
#define DATA_LEN_REQUEST_SENSE 14
#define CBW_CB_LENGTH 16
#define CBW_LENGTH 10
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_SENSE_KEY_NO_SENSE 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_ASC_NO_ADDITIONAL_SENSE_INFORMATION 0x00
#define SCSI_ASC_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASC_WRITE_PROTECTED 0x27
#define SCSI_ASC_FORMAT_ERROR 0x31
#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup _Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
uint8_t lun);
USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_CapacityTypeDef *capacity);
USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_StdInquiryDataTypeDef *inquiry);
USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_SenseTypeDef *sense_data);
USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_MSC_SCSI_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,805 @@
/**
******************************************************************************
* @file usbh_msc.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements the MSC class driver functions
* ===================================================================
* MSC Class Description
* ===================================================================
* This module manages the MSC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_msc.h"
#include "usbh_msc_bot.h"
#include "usbh_msc_scsi.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun);
USBH_ClassTypeDef USBH_msc =
{
"MSC",
USB_MSC_CLASS,
USBH_MSC_InterfaceInit,
USBH_MSC_InterfaceDeInit,
USBH_MSC_ClassRequest,
USBH_MSC_Process,
USBH_MSC_SOFProcess,
NULL,
};
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_InterfaceInit
* The function init the MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost)
{
uint8_t interface = 0;
USBH_StatusTypeDef status = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle;
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, MSC_TRANSPARENT, MSC_BOT);
if(interface == 0xFF) /* Not Valid Interface */
{
USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
status = USBH_FAIL;
}
else
{
USBH_SelectInterface (phost, interface);
phost->pActiveClass->pData = (MSC_HandleTypeDef *)USBH_malloc (sizeof(MSC_HandleTypeDef));
MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress & 0x80)
{
MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress);
MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
}
else
{
MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress);
MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
}
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress & 0x80)
{
MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress);
MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize;
}
else
{
MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress);
MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize;
}
MSC_Handle->current_lun = 0;
MSC_Handle->rw_lun = 0;
MSC_Handle->state = MSC_INIT;
MSC_Handle->error = MSC_OK;
MSC_Handle->req_state = MSC_REQ_IDLE;
MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp);
MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp);
USBH_MSC_BOT_Init(phost);
/* De-Initialize LUNs information */
USBH_memset(MSC_Handle->unit, 0, sizeof(MSC_Handle->unit));
/* Open the new channels */
USBH_OpenPipe (phost,
MSC_Handle->OutPipe,
MSC_Handle->OutEp,
phost->device.address,
phost->device.speed,
USB_EP_TYPE_BULK,
MSC_Handle->OutEpSize);
USBH_OpenPipe (phost,
MSC_Handle->InPipe,
MSC_Handle->InEp,
phost->device.address,
phost->device.speed,
USB_EP_TYPE_BULK,
MSC_Handle->InEpSize);
USBH_LL_SetToggle (phost, MSC_Handle->InPipe,0);
USBH_LL_SetToggle (phost, MSC_Handle->OutPipe,0);
status = USBH_OK;
}
return status;
}
/**
* @brief USBH_MSC_InterfaceDeInit
* The function DeInit the Pipes used for the MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if ( MSC_Handle->OutPipe)
{
USBH_ClosePipe(phost, MSC_Handle->OutPipe);
USBH_FreePipe (phost, MSC_Handle->OutPipe);
MSC_Handle->OutPipe = 0; /* Reset the Channel as Free */
}
if ( MSC_Handle->InPipe)
{
USBH_ClosePipe(phost, MSC_Handle->InPipe);
USBH_FreePipe (phost, MSC_Handle->InPipe);
MSC_Handle->InPipe = 0; /* Reset the Channel as Free */
}
if(phost->pActiveClass->pData)
{
USBH_free (phost->pActiveClass->pData);
phost->pActiveClass->pData = 0;
}
return USBH_OK;
}
/**
* @brief USBH_MSC_ClassRequest
* The function is responsible for handling Standard requests
* for MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
USBH_StatusTypeDef status = USBH_BUSY;
uint8_t i;
/* Switch MSC REQ state machine */
switch (MSC_Handle->req_state)
{
case MSC_REQ_IDLE:
case MSC_REQ_GET_MAX_LUN:
/* Issue GetMaxLUN request */
status = USBH_MSC_BOT_REQ_GetMaxLUN(phost, (uint8_t *)&MSC_Handle->max_lun);
/* When devices do not support the GetMaxLun request, this should
be considred as only one logical unit is supported */
if(status == USBH_NOT_SUPPORTED)
{
MSC_Handle->max_lun = 0;
status = USBH_OK;
}
if(status == USBH_OK)
{
MSC_Handle->max_lun = (uint8_t )(MSC_Handle->max_lun) + 1;
USBH_UsrLog ("Number of supported LUN: %lu", (int32_t)(MSC_Handle->max_lun));
for(i = 0; i < MSC_Handle->max_lun; i++)
{
MSC_Handle->unit[i].prev_ready_state = USBH_FAIL;
MSC_Handle->unit[i].state_changed = 0;
}
}
break;
case MSC_REQ_ERROR :
/* a Clear Feature should be issued here */
if(USBH_ClrFeature(phost, 0x00) == USBH_OK)
{
MSC_Handle->req_state = MSC_Handle->prev_req_state;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_Process
* The function is for managing state machine for MSC data transfers
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
USBH_StatusTypeDef error = USBH_BUSY ;
USBH_StatusTypeDef scsi_status = USBH_BUSY ;
USBH_StatusTypeDef ready_status = USBH_BUSY ;
switch (MSC_Handle->state)
{
case MSC_INIT:
if(MSC_Handle->current_lun < MSC_Handle->max_lun)
{
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY;
/* Switch MSC REQ state machine */
switch (MSC_Handle->unit[MSC_Handle->current_lun].state)
{
case MSC_INIT:
USBH_UsrLog ("LUN #%d: ", MSC_Handle->current_lun);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY;
MSC_Handle->timer = phost->Timer;
case MSC_READ_INQUIRY:
scsi_status = USBH_MSC_SCSI_Inquiry(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry);
if( scsi_status == USBH_OK)
{
USBH_UsrLog ("Inquiry Vendor : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.vendor_id);
USBH_UsrLog ("Inquiry Product : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.product_id);
USBH_UsrLog ("Inquiry Version : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.revision_id);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY;
}
if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_TEST_UNIT_READY:
ready_status = USBH_MSC_SCSI_TestUnitReady(phost, MSC_Handle->current_lun);
if( ready_status == USBH_OK)
{
if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_OK)
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1;
USBH_UsrLog ("MSC Device ready");
}
else
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0;
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_CAPACITY10;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK;
MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_OK;
}
if( ready_status == USBH_FAIL)
{
/* Media not ready, so try to check again during 10s */
if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1;
USBH_UsrLog ("MSC Device NOT ready");
}
else
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0;
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY;
MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_FAIL;
}
else if(ready_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_READ_CAPACITY10:
scsi_status = USBH_MSC_SCSI_ReadCapacity(phost,MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].capacity) ;
if(scsi_status == USBH_OK)
{
if(MSC_Handle->unit[MSC_Handle->current_lun].state_changed == 1)
{
USBH_UsrLog ("MSC Device capacity : %lu Bytes", \
(int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size));
USBH_UsrLog ("Block number : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr));
USBH_UsrLog ("Block Size : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size));
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK;
MSC_Handle->current_lun++;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_REQUEST_SENSE:
scsi_status = USBH_MSC_SCSI_RequestSense(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].sense);
if( scsi_status == USBH_OK)
{
if((MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION) ||
(MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY) )
{
if((phost->Timer - MSC_Handle->timer) < 10000)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY;
break;
}
}
USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.key);
USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.asc);
USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.ascq);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->current_lun++;
}
if( scsi_status == USBH_FAIL)
{
USBH_UsrLog ("MSC Device NOT ready");
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_UNRECOVERED_ERROR;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_UNRECOVERED_ERROR:
MSC_Handle->current_lun++;
break;
default:
break;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif
}
else
{
MSC_Handle->current_lun = 0;
MSC_Handle->state = MSC_IDLE;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif
phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
}
break;
case MSC_IDLE:
error = USBH_OK;
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SOFProcess
* The function is for SOF state
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_MSC_RdWrProcess
* The function is for managing state machine for MSC I/O Process
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
USBH_StatusTypeDef error = USBH_BUSY ;
USBH_StatusTypeDef scsi_status = USBH_BUSY ;
/* Switch MSC REQ state machine */
switch (MSC_Handle->unit[lun].state)
{
case MSC_READ:
scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, NULL, 0) ;
if(scsi_status == USBH_OK)
{
MSC_Handle->unit[lun].state = MSC_IDLE;
error = USBH_OK;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif
break;
case MSC_WRITE:
scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, NULL, 0) ;
if(scsi_status == USBH_OK)
{
MSC_Handle->unit[lun].state = MSC_IDLE;
error = USBH_OK;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif
break;
case MSC_REQUEST_SENSE:
scsi_status = USBH_MSC_SCSI_RequestSense(phost, lun, &MSC_Handle->unit[lun].sense);
if( scsi_status == USBH_OK)
{
USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[lun].sense.key);
USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[lun].sense.asc);
USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq);
MSC_Handle->unit[lun].state = MSC_IDLE;
MSC_Handle->unit[lun].error = MSC_ERROR;
error = USBH_FAIL;
}
if( scsi_status == USBH_FAIL)
{
USBH_UsrLog ("MSC Device NOT ready");
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_IsReady
* The function check if the MSC function is ready
* @param phost: Host handle
* @retval USBH Status
*/
uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
return (MSC_Handle->state == MSC_IDLE);
}
else
{
return 0;
}
}
/**
* @brief USBH_MSC_GetMaxLUN
* The function return the Max LUN supported
* @param phost: Host handle
* @retval logical Unit Number supported
*/
int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if ((phost->gState == HOST_CLASS) && (MSC_Handle->state == MSC_IDLE))
{
return MSC_Handle->max_lun;
}
return 0xFF;
}
/**
* @brief USBH_MSC_UnitIsReady
* The function check whether a LUN is ready
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval Lun status (0: not ready / 1: ready)
*/
uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
return (MSC_Handle->unit[lun].error == MSC_OK);
}
else
{
return 0;
}
}
/**
* @brief USBH_MSC_GetLUNInfo
* The function return a LUN information
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
USBH_memcpy(info,&MSC_Handle->unit[lun], sizeof(MSC_LUNTypeDef));
return USBH_OK;
}
else
{
return USBH_FAIL;
}
}
/**
* @brief USBH_MSC_Read
* The function performs a Read operation
* @param phost: Host handle
* @param lun: logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to read
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
uint32_t timeout;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if ((phost->device.is_connected == 0) ||
(phost->gState != HOST_CLASS) ||
(MSC_Handle->unit[lun].state != MSC_IDLE))
{
return USBH_FAIL;
}
MSC_Handle->state = MSC_READ;
MSC_Handle->unit[lun].state = MSC_READ;
MSC_Handle->rw_lun = lun;
USBH_MSC_SCSI_Read(phost,
lun,
address,
pbuf,
length);
timeout = phost->Timer;
while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
{
if(((phost->Timer - timeout) > (10000 * length)) || (phost->device.is_connected == 0))
{
MSC_Handle->state = MSC_IDLE;
return USBH_FAIL;
}
}
MSC_Handle->state = MSC_IDLE;
return USBH_OK;
}
/**
* @brief USBH_MSC_Write
* The function performs a Write operation
* @param phost: Host handle
* @param lun: logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to write
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
uint32_t timeout;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
if ((phost->device.is_connected == 0) ||
(phost->gState != HOST_CLASS) ||
(MSC_Handle->unit[lun].state != MSC_IDLE))
{
return USBH_FAIL;
}
MSC_Handle->state = MSC_WRITE;
MSC_Handle->unit[lun].state = MSC_WRITE;
MSC_Handle->rw_lun = lun;
USBH_MSC_SCSI_Write(phost,
lun,
address,
pbuf,
length);
timeout = phost->Timer;
while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
{
if(((phost->Timer - timeout) > (10000 * length)) || (phost->device.is_connected == 0))
{
MSC_Handle->state = MSC_IDLE;
return USBH_FAIL;
}
}
MSC_Handle->state = MSC_IDLE;
return USBH_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,633 @@
/**
******************************************************************************
* @file usbh_msc_bot.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file includes the BOT protocol related functions
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_msc_bot.h"
#include "usbh_msc.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_BOT_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir);
static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost);
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_BOT_REQ_Reset
* The function the MSC BOT Reset request.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_MSC_BOT_REQ_GetMaxLUN
* The function the MSC BOT GetMaxLUN request.
* @param phost: Host handle
* @param Maxlun: pointer to Maxlun variable
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun)
{
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 1;
return USBH_CtlReq(phost, Maxlun , 1 );
}
/**
* @brief USBH_MSC_BOT_Init
* The function Initializes the BOT protocol.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE;
MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
return USBH_OK;
}
/**
* @brief USBH_MSC_BOT_Process
* The function handle the BOT protocol.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
USBH_StatusTypeDef status = USBH_BUSY;
USBH_StatusTypeDef error = USBH_BUSY;
BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED;
USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
uint8_t toggle = 0;
switch (MSC_Handle->hbot.state)
{
case BOT_SEND_CBW:
MSC_Handle->hbot.cbw.field.LUN = lun;
MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;
USBH_BulkSendData (phost,
MSC_Handle->hbot.cbw.data,
BOT_CBW_LENGTH,
MSC_Handle->OutPipe,
1);
break;
case BOT_SEND_CBW_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
if(URB_Status == USBH_URB_DONE)
{
if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
{
/* If there is Data Transfer Stage */
if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
{
/* Data Direction is IN */
MSC_Handle->hbot.state = BOT_DATA_IN;
}
else
{
/* Data Direction is OUT */
MSC_Handle->hbot.state = BOT_DATA_OUT;
}
}
else
{/* If there is NO Data Transfer Stage */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_NOTREADY)
{
/* Re-send CBW */
MSC_Handle->hbot.state = BOT_SEND_CBW;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_OUT;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
break;
case BOT_DATA_IN:
/* Send first packet */
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->InEpSize ,
MSC_Handle->InPipe);
MSC_Handle->hbot.state = BOT_DATA_IN_WAIT;
break;
case BOT_DATA_IN_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
if(URB_Status == USBH_URB_DONE)
{
/* Adjust Data pointer and data length */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
{
MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;
}
else
{
MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
}
/* More Data To be Received */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
{
/* Send next packet */
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->InEpSize ,
MSC_Handle->InPipe);
}
else
{
/* If value was 0, and successful transfer, then change the state */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
}
else if(URB_Status == USBH_URB_STALL)
{
/* This is Data IN Stage STALL Condition */
MSC_Handle->hbot.state = BOT_ERROR_IN;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.2 Host expects to receive data from the device
3. On a STALL condition receiving data, then:
The host shall accept the data received.
The host shall clear the Bulk-In pipe.
4. The host shall attempt to receive a CSW.*/
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
break;
case BOT_DATA_OUT:
USBH_BulkSendData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->OutEpSize ,
MSC_Handle->OutPipe,
1);
MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT;
break;
case BOT_DATA_OUT_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
if(URB_Status == USBH_URB_DONE)
{
/* Adjust Data pointer and data length */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
{
MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize;
}
else
{
MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
}
/* More Data To be Sent */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
{
USBH_BulkSendData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->OutEpSize ,
MSC_Handle->OutPipe,
1);
}
else
{
/* If value was 0, and successful transfer, then change the state */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_NOTREADY)
{
/* Resend same data */
MSC_Handle->hbot.state = BOT_DATA_OUT;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_OUT;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.3 Ho - Host expects to send data to the device
3. On a STALL condition sending data, then:
" The host shall clear the Bulk-Out pipe.
4. The host shall attempt to receive a CSW.
*/
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
break;
case BOT_RECEIVE_CSW:
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.csw.data,
BOT_CSW_LENGTH ,
MSC_Handle->InPipe);
MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT;
break;
case BOT_RECEIVE_CSW_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
/* Decode CSW */
if(URB_Status == USBH_URB_DONE)
{
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
CSW_Status = USBH_MSC_DecodeCSW(phost);
if(CSW_Status == BOT_CSW_CMD_PASSED)
{
status = USBH_OK;
}
else
{
status = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_IN;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
break;
case BOT_ERROR_IN:
error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);
if (error == USBH_OK)
{
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
else if (error == USBH_UNRECOVERED_ERROR)
{
/* This means that there is a STALL Error limit, Do Reset Recovery */
MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
}
break;
case BOT_ERROR_OUT:
error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);
if ( error == USBH_OK)
{
toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe);
USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);
USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);
MSC_Handle->hbot.state = BOT_ERROR_IN;
}
else if (error == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
}
break;
case BOT_UNRECOVERED_ERROR:
status = USBH_MSC_BOT_REQ_Reset(phost);
if ( status == USBH_OK)
{
MSC_Handle->hbot.state = BOT_SEND_CBW;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_BOT_Abort
* The function handle the BOT Abort process.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param dir: direction (0: out / 1 : in)
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir)
{
USBH_StatusTypeDef status = USBH_FAIL;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch (dir)
{
case BOT_DIR_IN :
/* send ClrFeture on Bulk IN endpoint */
status = USBH_ClrFeature(phost, MSC_Handle->InEp);
break;
case BOT_DIR_OUT :
/*send ClrFeature on Bulk OUT endpoint */
status = USBH_ClrFeature(phost, MSC_Handle->OutEp);
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_BOT_DecodeCSW
* This function decodes the CSW received by the device and updates the
* same to upper layer.
* @param phost: Host handle
* @retval USBH Status
* @notes
* Refer to USB Mass-Storage Class : BOT (www.usb.org)
* 6.3.1 Valid CSW Conditions :
* The host shall consider the CSW valid when:
* 1. dCSWSignature is equal to 53425355h
* 2. the CSW is 13 (Dh) bytes in length,
* 3. dCSWTag matches the dCBWTag from the corresponding CBW.
*/
static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED;
/*Checking if the transfer length is different than 13*/
if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH)
{
/*(4) Hi > Dn (Host expects to receive data from the device,
Device intends to transfer no data)
(5) Hi > Di (Host expects to receive data from the device,
Device intends to send data to the host)
(9) Ho > Dn (Host expects to send data to the device,
Device intends to transfer no data)
(11) Ho > Do (Host expects to send data to the device,
Device intends to receive data from the host)*/
status = BOT_CSW_PHASE_ERROR;
}
else
{ /* CSW length is Correct */
/* Check validity of the CSW Signature and CSWStatus */
if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE)
{/* Check Condition 1. dCSWSignature is equal to 53425355h */
if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag)
{
/* Check Condition 3. dCSWTag matches the dCBWTag from the
corresponding CBW */
if(MSC_Handle->hbot.csw.field.Status == 0)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Hn Host expects no data transfers
Hi Host expects to receive data from the device
Ho Host expects to send data to the device
Dn Device intends to transfer no data
Di Device intends to send data to the host
Do Device intends to receive data from the host
Section 6.7
(1) Hn = Dn (Host expects no data transfers,
Device intends to transfer no data)
(6) Hi = Di (Host expects to receive data from the device,
Device intends to send data to the host)
(12) Ho = Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = BOT_CSW_CMD_PASSED;
}
else if(MSC_Handle->hbot.csw.field.Status == 1)
{
status = BOT_CSW_CMD_FAILED;
}
else if(MSC_Handle->hbot.csw.field.Status == 2)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Section 6.7
(2) Hn < Di ( Host expects no data transfers,
Device intends to send data to the host)
(3) Hn < Do ( Host expects no data transfers,
Device intends to receive data from the host)
(7) Hi < Di ( Host expects to receive data from the device,
Device intends to send data to the host)
(8) Hi <> Do ( Host expects to receive data from the device,
Device intends to receive data from the host)
(10) Ho <> Di (Host expects to send data to the device,
Di Device intends to send data to the host)
(13) Ho < Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = BOT_CSW_PHASE_ERROR;
}
} /* CSW Tag Matching is Checked */
} /* CSW Signature Correct Checking */
else
{
/* If the CSW Signature is not valid, We sall return the Phase Error to
Upper Layers for Reset Recovery */
status = BOT_CSW_PHASE_ERROR;
}
} /* CSW Length Check*/
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,458 @@
/**
******************************************************************************
* @file usbh_msc_scsi.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements the SCSI commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_msc.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_SCSI_TestUnitReady
* Issue TestUnitReady command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
uint8_t lun)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_ReadCapacity
* Issue Read Capacity command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the capacity structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_CapacityTypeDef *capacity)
{
USBH_StatusTypeDef error = USBH_BUSY ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
/*assign the capacity*/
capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\
(MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24);
/*assign the page length*/
capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8);
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Inquiry
* Issue Inquiry command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the inquiry structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_StdInquiryDataTypeDef *inquiry)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY;
MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
MSC_Handle->hbot.cbw.field.CB[2] = 0;
MSC_Handle->hbot.cbw.field.CB[3] = 0;
MSC_Handle->hbot.cbw.field.CB[4] = 0x24;
MSC_Handle->hbot.cbw.field.CB[5] = 0;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef));
/*assign Inquiry Data */
inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F;
inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5;
inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80;
USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8);
USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16);
USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4);
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_RequestSense
* Issue RequestSense command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the sense data structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_SenseTypeDef *sense_data)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
MSC_Handle->hbot.cbw.field.CB[2] = 0;
MSC_Handle->hbot.cbw.field.CB[3] = 0;
MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.CB[5] = 0;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F;
sense_data->asc = MSC_Handle->hbot.pbuf[12];
sense_data->ascq = MSC_Handle->hbot.pbuf[13];
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Write
* Issue write10 command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to write
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10;
/*logical block address*/
MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
/*Transfer length */
MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = pbuf;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Read
* Issue Read10 command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to read
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10;
/*logical block address*/
MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
/*Transfer length */
MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = pbuf;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,157 @@
/**
******************************************************************************
* @file usbh_conf_template.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_conf_template.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBH_CONF_TEMPLATE_H
#define __USBH_CONF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup USBH_OTG_DRIVER
* @{
*/
/** @defgroup USBH_CONF
* @brief usb otg low level driver configuration file
* @{
*/
/** @defgroup USBH_CONF_Exported_Defines
* @{
*/
#define USBH_MAX_NUM_ENDPOINTS 2
#define USBH_MAX_NUM_INTERFACES 2
#define USBH_MAX_NUM_CONFIGURATION 1
#define USBH_KEEP_CFG_DESCRIPTOR 1
#define USBH_MAX_NUM_SUPPORTED_CLASS 1
#define USBH_MAX_SIZE_CONFIGURATION 0x200
#define USBH_MAX_DATA_BUFFER 0x200
#define USBH_DEBUG_LEVEL 2
#define USBH_USE_OS 1
/** @defgroup USBH_Exported_Macros
* @{
*/
/* Memory management macros */
#define USBH_malloc malloc
#define USBH_free free
#define USBH_memset memset
#define USBH_memcpy memcpy
/* DEBUG macros */
#if (USBH_DEBUG_LEVEL > 0)
#define USBH_UsrLog(...) printf(__VA_ARGS__);\
printf("\n");
#else
#define USBH_UsrLog(...)
#endif
#if (USBH_DEBUG_LEVEL > 1)
#define USBH_ErrLog(...) printf("ERROR: ") ;\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBH_ErrLog(...)
#endif
#if (USBH_DEBUG_LEVEL > 2)
#define USBH_DbgLog(...) printf("DEBUG : ") ;\
printf(__VA_ARGS__);\
printf("\n");
#else
#define USBH_DbgLog(...)
#endif
/**
* @}
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_CONF_TEMPLATE_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,169 @@
/**
******************************************************************************
* @file usbh_core.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_core.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_CORE_H
#define __USBH_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_conf.h"
#include "usbh_def.h"
#include "usbh_ioreq.h"
#include "usbh_pipes.h"
#include "usbh_ctlreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_CORE
* @brief This file is the Header file for usbh_core.c
* @{
*/
/** @defgroup USBH_CORE_Exported_Defines
* @{
*/
/**
* @}
*/
#define HOST_USER_SELECT_CONFIGURATION 1
#define HOST_USER_CLASS_ACTIVE 2
#define HOST_USER_CLASS_SELECTED 3
#define HOST_USER_CONNECTION 4
#define HOST_USER_DISCONNECTION 5
#define HOST_USER_UNRECOVERED_ERROR 6
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id);
USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass);
USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface);
uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost,
uint8_t Class,
uint8_t SubClass,
uint8_t Protocol);
uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost);
uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost,
uint8_t interface_number,
uint8_t alt_settings);
USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_Process (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost);
/* USBH Low Level Driver */
USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_Start (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost);
USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost);
uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t );
USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t );
USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, uint8_t, uint8_t, uint8_t, uint8_t , uint8_t, uint16_t );
USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t );
USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, uint8_t, uint8_t,uint8_t, uint8_t, uint8_t*, uint16_t, uint8_t );
USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t );
#if (USBH_USE_OS == 1)
USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost);
#endif
USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t , uint8_t );
uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t );
/* USBH Time base */
void USBH_Delay (uint32_t Delay);
void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t );
void USBH_LL_IncTimer (USBH_HandleTypeDef *phost);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_CORE_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,155 @@
/**
******************************************************************************
* @file usbh_ctlreq.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_ctlreq.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_CTLREQ_H
#define __USBH_CTLREQ_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_CTLREQ
* @brief This file is the
* @{
*/
/** @defgroup USBH_CTLREQ_Exported_Defines
* @{
*/
/*Standard Feature Selector for clear feature command*/
#define FEATURE_SELECTOR_ENDPOINT 0X00
#define FEATURE_SELECTOR_DEVICE 0X01
#define INTERFACE_DESC_TYPE 0x04
#define ENDPOINT_DESC_TYPE 0x05
#define INTERFACE_DESC_SIZE 0x09
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Exported_Variables
* @{
*/
extern uint8_t USBH_CfgDesc[512];
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length);
USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost,
uint8_t req_type,
uint16_t value_idx,
uint8_t* buff,
uint16_t length );
USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost,
uint8_t length);
USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost,
uint8_t string_index,
uint8_t *buff,
uint16_t length);
USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost,
uint16_t configuration_value);
USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,
uint16_t length);
USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost,
uint8_t DeviceAddress);
USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost,
uint8_t ep_num, uint8_t altSetting);
USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost,
uint8_t ep_num);
USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf,
uint16_t *ptr);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_CTLREQ_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,490 @@
/**
******************************************************************************
* @file usbh_def.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Definitions used in the USB host library
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef USBH_DEF_H
#define USBH_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_conf.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_DEF
* @brief This file is includes USB descriptors
* @{
*/
#ifndef NULL
#define NULL 0
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define ValBit(VAR,POS) (VAR & (1 << POS))
#define SetBit(VAR,POS) (VAR |= (1 << POS))
#define ClrBit(VAR,POS) (VAR &= ((1 << POS)^255))
#define LE16(addr) (((uint16_t)(*((uint8_t *)(addr))))\
+ (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
#define LE16S(addr) (uint16_t)(LE16((addr)))
#define LE32(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \
(((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \
(((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16) + \
(((uint32_t)(*(((uint8_t *)(addr)) + 3))) << 24)))
#define LE64(addr) ((((uint64_t)(*(((uint8_t *)(addr)) + 0))) + \
(((uint64_t)(*(((uint8_t *)(addr)) + 1))) << 8) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 2))) << 16) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 3))) << 24) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 4))) << 32) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 5))) << 40) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 6))) << 48) +\
(((uint64_t)(*(((uint8_t *)(addr)) + 7))) << 56)))
#define LE24(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \
(((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \
(((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16)))
#define LE32S(addr) (int32_t)(LE32((addr)))
#define USB_LEN_DESC_HDR 0x02
#define USB_LEN_DEV_DESC 0x12
#define USB_LEN_CFG_DESC 0x09
#define USB_LEN_IF_DESC 0x09
#define USB_LEN_EP_DESC 0x07
#define USB_LEN_OTG_DESC 0x03
#define USB_LEN_SETUP_PKT 0x08
/* bmRequestType :D7 Data Phase Transfer Direction */
#define USB_REQ_DIR_MASK 0x80
#define USB_H2D 0x00
#define USB_D2H 0x80
/* bmRequestType D6..5 Type */
#define USB_REQ_TYPE_STANDARD 0x00
#define USB_REQ_TYPE_CLASS 0x20
#define USB_REQ_TYPE_VENDOR 0x40
#define USB_REQ_TYPE_RESERVED 0x60
/* bmRequestType D4..0 Recipient */
#define USB_REQ_RECIPIENT_DEVICE 0x00
#define USB_REQ_RECIPIENT_INTERFACE 0x01
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
#define USB_REQ_RECIPIENT_OTHER 0x03
/* Table 9-4. Standard Request Codes */
/* bRequest , Value */
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
/* Table 9-5. Descriptor Types of USB Specifications */
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
#define USB_DESC_TYPE_INTERFACE_POWER 8
#define USB_DESC_TYPE_HID 0x21
#define USB_DESC_TYPE_HID_REPORT 0x22
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGURATION_DESC_SIZE 9
#define USB_HID_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
/* Descriptor Type and Descriptor Index */
/* Use the following values when calling the function USBH_GetDescriptor */
#define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00)
#define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00)
#define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00)
#define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00)
#define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00)
#define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00)
#define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00)
#define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00)
#define USB_EP_TYPE_CTRL 0x00
#define USB_EP_TYPE_ISOC 0x01
#define USB_EP_TYPE_BULK 0x02
#define USB_EP_TYPE_INTR 0x03
#define USB_EP_DIR_OUT 0x00
#define USB_EP_DIR_IN 0x80
#define USB_EP_DIR_MSK 0x80
#ifndef USBH_MAX_PIPES_NBR
#define USBH_MAX_PIPES_NBR 15
#endif /* USBH_MAX_PIPES_NBR */
#define USBH_DEVICE_ADDRESS_DEFAULT 0
#define USBH_MAX_ERROR_COUNT 2
#define USBH_DEVICE_ADDRESS 1
/**
* @}
*/
#define USBH_CONFIGURATION_DESCRIPTOR_SIZE (USB_CONFIGURATION_DESC_SIZE \
+ USB_INTERFACE_DESC_SIZE\
+ (USBH_MAX_NUM_ENDPOINTS * USB_ENDPOINT_DESC_SIZE))
#define CONFIG_DESC_wTOTAL_LENGTH (ConfigurationDescriptorData.ConfigDescfield.\
ConfigurationDescriptor.wTotalLength)
typedef union
{
uint16_t w;
struct BW
{
uint8_t msb;
uint8_t lsb;
}
bw;
}
uint16_t_uint8_t;
typedef union _USB_Setup
{
uint32_t d8[2];
struct _SetupPkt_Struc
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
}
USB_Setup_TypeDef;
typedef struct _DescHeader
{
uint8_t bLength;
uint8_t bDescriptorType;
}
USBH_DescHeader_t;
typedef struct _DeviceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB; /* USB Specification Number which device complies too */
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
/* If equal to Zero, each interface specifies its own class
code if equal to 0xFF, the class code is vendor specified.
Otherwise field is valid Class Code.*/
uint8_t bMaxPacketSize;
uint16_t idVendor; /* Vendor ID (Assigned by USB Org) */
uint16_t idProduct; /* Product ID (Assigned by Manufacturer) */
uint16_t bcdDevice; /* Device Release Number */
uint8_t iManufacturer; /* Index of Manufacturer String Descriptor */
uint8_t iProduct; /* Index of Product String Descriptor */
uint8_t iSerialNumber; /* Index of Serial Number String Descriptor */
uint8_t bNumConfigurations; /* Number of Possible Configurations */
}
USBH_DevDescTypeDef;
typedef struct _EndpointDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress; /* indicates what endpoint this descriptor is describing */
uint8_t bmAttributes; /* specifies the transfer type. */
uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving */
uint8_t bInterval; /* is used to specify the polling interval of certain transfers. */
}
USBH_EpDescTypeDef;
typedef struct _InterfaceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting; /* Value used to select alternative setting */
uint8_t bNumEndpoints; /* Number of Endpoints used for this interface */
uint8_t bInterfaceClass; /* Class Code (Assigned by USB Org) */
uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */
uint8_t bInterfaceProtocol; /* Protocol Code */
uint8_t iInterface; /* Index of String Descriptor Describing this interface */
USBH_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS];
}
USBH_InterfaceDescTypeDef;
typedef struct _ConfigurationDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength; /* Total Length of Data Returned */
uint8_t bNumInterfaces; /* Number of Interfaces */
uint8_t bConfigurationValue; /* Value to use as an argument to select this configuration*/
uint8_t iConfiguration; /*Index of String Descriptor Describing this configuration */
uint8_t bmAttributes; /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/
uint8_t bMaxPower; /*Maximum Power Consumption */
USBH_InterfaceDescTypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES];
}
USBH_CfgDescTypeDef;
/* Following USB Host status */
typedef enum
{
USBH_OK = 0,
USBH_BUSY,
USBH_FAIL,
USBH_NOT_SUPPORTED,
USBH_UNRECOVERED_ERROR,
USBH_ERROR_SPEED_UNKNOWN,
}USBH_StatusTypeDef;
/** @defgroup USBH_CORE_Exported_Types
* @{
*/
typedef enum
{
USBH_SPEED_HIGH = 0,
USBH_SPEED_FULL = 1,
USBH_SPEED_LOW = 2,
}USBH_SpeedTypeDef;
/* Following states are used for gState */
typedef enum
{
HOST_IDLE =0,
HOST_DEV_WAIT_FOR_ATTACHMENT,
HOST_DEV_ATTACHED,
HOST_DEV_DISCONNECTED,
HOST_DETECT_DEVICE_SPEED,
HOST_ENUMERATION,
HOST_CLASS_REQUEST,
HOST_INPUT,
HOST_SET_CONFIGURATION,
HOST_CHECK_CLASS,
HOST_CLASS,
HOST_SUSPENDED,
HOST_ABORT_STATE,
}HOST_StateTypeDef;
/* Following states are used for EnumerationState */
typedef enum
{
ENUM_IDLE = 0,
ENUM_GET_FULL_DEV_DESC,
ENUM_SET_ADDR,
ENUM_GET_CFG_DESC,
ENUM_GET_FULL_CFG_DESC,
ENUM_GET_MFC_STRING_DESC,
ENUM_GET_PRODUCT_STRING_DESC,
ENUM_GET_SERIALNUM_STRING_DESC,
} ENUM_StateTypeDef;
/* Following states are used for CtrlXferStateMachine */
typedef enum
{
CTRL_IDLE =0,
CTRL_SETUP,
CTRL_SETUP_WAIT,
CTRL_DATA_IN,
CTRL_DATA_IN_WAIT,
CTRL_DATA_OUT,
CTRL_DATA_OUT_WAIT,
CTRL_STATUS_IN,
CTRL_STATUS_IN_WAIT,
CTRL_STATUS_OUT,
CTRL_STATUS_OUT_WAIT,
CTRL_ERROR,
CTRL_STALLED,
CTRL_COMPLETE
}CTRL_StateTypeDef;
/* Following states are used for RequestState */
typedef enum
{
CMD_IDLE =0,
CMD_SEND,
CMD_WAIT
} CMD_StateTypeDef;
typedef enum {
USBH_URB_IDLE = 0,
USBH_URB_DONE,
USBH_URB_NOTREADY,
USBH_URB_NYET,
USBH_URB_ERROR,
USBH_URB_STALL
}USBH_URBStateTypeDef;
typedef enum
{
USBH_PORT_EVENT = 1,
USBH_URB_EVENT,
USBH_CONTROL_EVENT,
USBH_CLASS_EVENT,
USBH_STATE_CHANGED_EVENT,
}
USBH_OSEventTypeDef;
/* Control request structure */
typedef struct
{
uint8_t pipe_in;
uint8_t pipe_out;
uint8_t pipe_size;
uint8_t *buff;
uint16_t length;
uint16_t timer;
USB_Setup_TypeDef setup;
CTRL_StateTypeDef state;
uint8_t errorcount;
} USBH_CtrlTypeDef;
/* Attached device structure */
typedef struct
{
#if (USBH_KEEP_CFG_DESCRIPTOR == 1)
uint8_t CfgDesc_Raw[USBH_MAX_SIZE_CONFIGURATION];
#endif
uint8_t Data[USBH_MAX_DATA_BUFFER];
uint8_t address;
uint8_t speed;
__IO uint8_t is_connected;
uint8_t current_interface;
USBH_DevDescTypeDef DevDesc;
USBH_CfgDescTypeDef CfgDesc;
}USBH_DeviceTypeDef;
struct _USBH_HandleTypeDef;
/* USB Host Class structure */
typedef struct
{
const char *Name;
uint8_t ClassCode;
USBH_StatusTypeDef (*Init) (struct _USBH_HandleTypeDef *phost);
USBH_StatusTypeDef (*DeInit) (struct _USBH_HandleTypeDef *phost);
USBH_StatusTypeDef (*Requests) (struct _USBH_HandleTypeDef *phost);
USBH_StatusTypeDef (*BgndProcess) (struct _USBH_HandleTypeDef *phost);
USBH_StatusTypeDef (*SOFProcess) (struct _USBH_HandleTypeDef *phost);
void* pData;
} USBH_ClassTypeDef;
/* USB Host handle structure */
typedef struct _USBH_HandleTypeDef
{
__IO HOST_StateTypeDef gState; /* Host State Machine Value */
ENUM_StateTypeDef EnumState; /* Enumeration state Machine */
CMD_StateTypeDef RequestState;
USBH_CtrlTypeDef Control;
USBH_DeviceTypeDef device;
USBH_ClassTypeDef* pClass[USBH_MAX_NUM_SUPPORTED_CLASS];
USBH_ClassTypeDef* pActiveClass;
uint32_t ClassNumber;
uint32_t Pipes[15];
__IO uint32_t Timer;
uint8_t id;
void* pData;
void (* pUser )(struct _USBH_HandleTypeDef *pHandle, uint8_t id);
#if (USBH_USE_OS == 1)
osMessageQId os_event;
osThreadId thread;
#endif
} USBH_HandleTypeDef;
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))
#endif /* __weak */
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif /* __packed */
#endif /* __GNUC__ */
#ifdef __cplusplus
}
#endif
#endif /* USBH_DEF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,168 @@
/**
******************************************************************************
* @file usbh_ioreq.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_ioreq.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_IOREQ_H
#define __USBH_IOREQ_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_conf.h"
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_IOREQ
* @brief This file is the header file for usbh_ioreq.c
* @{
*/
/** @defgroup USBH_IOREQ_Exported_Defines
* @{
*/
#define USBH_PID_SETUP 0
#define USBH_PID_DATA 1
#define USBH_EP_CONTROL 0
#define USBH_EP_ISO 1
#define USBH_EP_BULK 2
#define USBH_EP_INTERRUPT 3
#define USBH_SETUP_PKT_SIZE 8
/**
* @}
*/
/** @defgroup USBH_IOREQ_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t hc_num);
USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t hc_num,
uint8_t do_ping );
USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t hc_num);
USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t hc_num);
USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t hc_num,
uint8_t do_ping );
USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t hc_num);
USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t hc_num);
USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t hc_num);
USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t hc_num);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_IOREQ_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,131 @@
/**
******************************************************************************
* @file usbh_pipes.h
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief Header file for usbh_pipes.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_PIPES_H
#define __USBH_PIPES_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_PIPES
* @brief This file is the header file for usbh_pipes.c
* @{
*/
/** @defgroup USBH_PIPES_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t ch_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num);
uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost,
uint8_t ep_addr);
USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost,
uint8_t idx);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_PIPES_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,271 @@
/**
******************************************************************************
* @file usb_bsp.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements the board support package for the USB host library
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_core.h"
/**
* @brief USBH_LL_Init
* Initialize the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_DeInit
* De-Initialize the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_Start
* Start the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_Stop
* Stop the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetSpeed
* Return the USB Host Speed from the Low Level Driver.
* @param phost: Host handle
* @retval USBH Speeds
*/
USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost)
{
USBH_SpeedTypeDef speed = USBH_SPEED_FULL;
return speed;
}
/**
* @brief USBH_LL_ResetPort
* Reset the Host Port of the Low Level Driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetLastXferSize
* Return the last transferred packet size.
* @param phost: Host handle
* @param pipe: Pipe index
* @retval Packet Size
*/
uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return 0;
}
/**
* @brief USBH_LL_OpenPipe
* Open a pipe of the Low Level Driver.
* @param phost: Host handle
* @param pipe_num: Pipe index
* @param epnum: Endpoint Number
* @param dev_address: Device USB address
* @param speed: Device Speed
* @param ep_type: Endpoint Type
* @param mps: Endpoint Max Packet Size
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
return USBH_OK;
}
/**
* @brief USBH_LL_ClosePipe
* Close a pipe of the Low Level Driver.
* @param phost: Host handle
* @param pipe_num: Pipe index
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return USBH_OK;
}
/**
* @brief USBH_LL_SubmitURB
* Submit a new URB to the low level driver.
* @param phost: Host handle
* @param pipe: Pipe index
* This parameter can be a value from 1 to 15
* @param direction : Channel number
* This parameter can be one of the these values:
* 0 : Output
* 1 : Input
* @param ep_type : Endpoint Type
* This parameter can be one of the these values:
* @arg EP_TYPE_CTRL: Control type
* @arg EP_TYPE_ISOC: Isochronous type
* @arg EP_TYPE_BULK: Bulk type
* @arg EP_TYPE_INTR: Interrupt type
* @param token : Endpoint Type
* This parameter can be one of the these values:
* @arg 0: PID_SETUP
* @arg 1: PID_DATA
* @param pbuff : pointer to URB data
* @param length : Length of URB data
* @param do_ping : activate do ping protocol (for high speed only)
* This parameter can be one of the these values:
* 0 : do ping inactive
* 1 : do ping active
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost,
uint8_t pipe,
uint8_t direction ,
uint8_t ep_type,
uint8_t token,
uint8_t* pbuff,
uint16_t length,
uint8_t do_ping )
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetURBState
* Get a URB state from the low level driver.
* @param phost: Host handle
* @param pipe: Pipe index
* This parameter can be a value from 1 to 15
* @retval URB state
* This parameter can be one of the these values:
* @arg URB_IDLE
* @arg URB_DONE
* @arg URB_NOTREADY
* @arg URB_NYET
* @arg URB_ERROR
* @arg URB_STALL
*/
USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return USBH_URB_IDLE;
}
/**
* @brief USBH_LL_DriverVBUS
* Drive VBUS.
* @param phost: Host handle
* @param state : VBUS state
* This parameter can be one of the these values:
* 0 : VBUS Active
* 1 : VBUS Inactive
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state)
{
return USBH_OK;
}
/**
* @brief USBH_LL_SetToggle
* Set toggle for a pipe.
* @param phost: Host handle
* @param pipe: Pipe index
* @param pipe_num: Pipe index
* @param toggle: toggle (0/1)
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetToggle
* Return the current toggle of a pipe.
* @param phost: Host handle
* @param pipe: Pipe index
* @retval toggle (0/1)
*/
uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe)
{
uint8_t toggle = 0;
return toggle;
}
/**
* @brief USBH_Delay
* Delay routine for the USB Host Library
* @param Delay: Delay in ms
* @retval None
*/
void USBH_Delay (uint32_t Delay)
{
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,933 @@
/**
******************************************************************************
* @file usbh_core.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements the functions for the core state machine process
* the enumeration and the control transfer process
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_CORE
* @brief This file handles the basic enumeration when a device is connected
* to the host.
* @{
*/
/** @defgroup USBH_CORE_Private_Defines
* @{
*/
#define USBH_ADDRESS_DEFAULT 0
#define USBH_ADDRESS_ASSIGNED 1
#define USBH_MPS_DEFAULT 0x40
/**
* @}
*/
/** @defgroup USBH_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Private_Functions
* @{
*/
static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost);
static void USBH_HandleSof (USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost);
#if (USBH_USE_OS == 1)
static void USBH_Process_OS(void const * argument);
#endif
/**
* @brief HCD_Init
* Initialize the HOST Core.
* @param phost: Host Handle
* @param pUsrFunc: User Callback
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id)
{
/* Check whether the USB Host handle is valid */
if(phost == NULL)
{
USBH_ErrLog("Invalid Host handle");
return USBH_FAIL;
}
/* Set DRiver ID */
phost->id = id;
/* Unlink class*/
phost->pActiveClass = NULL;
phost->ClassNumber = 0;
/* Restore default states and prepare EP0 */
DeInitStateMachine(phost);
/* Assign User process */
if(pUsrFunc != NULL)
{
phost->pUser = pUsrFunc;
}
#if (USBH_USE_OS == 1)
/* Create USB Host Queue */
osMessageQDef(USBH_Queue, 10, uint16_t);
phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL);
/*Create USB Host Task */
#if defined (USBH_PROCESS_STACK_SIZE)
osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, USBH_PROCESS_STACK_SIZE);
#else
osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE);
#endif
phost->thread = osThreadCreate (osThread(USBH_Thread), phost);
#endif
/* Initialize low level driver */
USBH_LL_Init(phost);
return USBH_OK;
}
/**
* @brief HCD_Init
* De-Initialize the Host portion of the driver.
* @param phost: Host Handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost)
{
DeInitStateMachine(phost);
if(phost->pData != NULL)
{
phost->pActiveClass->pData = NULL;
USBH_LL_Stop(phost);
}
return USBH_OK;
}
/**
* @brief DeInitStateMachine
* De-Initialize the Host state machine.
* @param phost: Host Handle
* @retval USBH Status
*/
static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost)
{
uint32_t i = 0;
/* Clear Pipes flags*/
for ( ; i < USBH_MAX_PIPES_NBR; i++)
{
phost->Pipes[i] = 0;
}
for(i = 0; i< USBH_MAX_DATA_BUFFER; i++)
{
phost->device.Data[i] = 0;
}
phost->gState = HOST_IDLE;
phost->EnumState = ENUM_IDLE;
phost->RequestState = CMD_SEND;
phost->Timer = 0;
phost->Control.state = CTRL_SETUP;
phost->Control.pipe_size = USBH_MPS_DEFAULT;
phost->Control.errorcount = 0;
phost->device.address = USBH_ADDRESS_DEFAULT;
phost->device.speed = USBH_SPEED_FULL;
return USBH_OK;
}
/**
* @brief USBH_RegisterClass
* Link class driver to Host Core.
* @param phost : Host Handle
* @param pclass: Class handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass)
{
USBH_StatusTypeDef status = USBH_OK;
if(pclass != 0)
{
if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS)
{
/* link the class to the USB Host handle */
phost->pClass[phost->ClassNumber++] = pclass;
status = USBH_OK;
}
else
{
USBH_ErrLog("Max Class Number reached");
status = USBH_FAIL;
}
}
else
{
USBH_ErrLog("Invalid Class handle");
status = USBH_FAIL;
}
return status;
}
/**
* @brief USBH_SelectInterface
* Select current interface.
* @param phost: Host Handle
* @param interface: Interface number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface)
{
USBH_StatusTypeDef status = USBH_OK;
if(interface < phost->device.CfgDesc.bNumInterfaces)
{
phost->device.current_interface = interface;
USBH_UsrLog ("Switching to Interface (#%d)", interface);
USBH_UsrLog ("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass );
USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass );
USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol );
}
else
{
USBH_ErrLog ("Cannot Select This Interface.");
status = USBH_FAIL;
}
return status;
}
/**
* @brief USBH_GetActiveClass
* Return Device Class.
* @param phost: Host Handle
* @param interface: Interface index
* @retval Class Code
*/
uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost)
{
return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass);
}
/**
* @brief USBH_FindInterface
* Find the interface index for a specific class.
* @param phost: Host Handle
* @param Class: Class code
* @param SubClass: SubClass code
* @param Protocol: Protocol code
* @retval interface index in the configuration structure
* @note : (1)interface index 0xFF means interface index not found
*/
uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol)
{
USBH_InterfaceDescTypeDef *pif ;
USBH_CfgDescTypeDef *pcfg ;
int8_t if_ix = 0;
pif = (USBH_InterfaceDescTypeDef *)0;
pcfg = &phost->device.CfgDesc;
while (if_ix < USBH_MAX_NUM_INTERFACES)
{
pif = &pcfg->Itf_Desc[if_ix];
if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&&
((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&&
((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF)))
{
return if_ix;
}
if_ix++;
}
return 0xFF;
}
/**
* @brief USBH_FindInterfaceIndex
* Find the interface index for a specific class interface and alternate setting number.
* @param phost: Host Handle
* @param interface_number: interface number
* @param alt_settings : alternate setting number
* @retval interface index in the configuration structure
* @note : (1)interface index 0xFF means interface index not found
*/
uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings)
{
USBH_InterfaceDescTypeDef *pif ;
USBH_CfgDescTypeDef *pcfg ;
int8_t if_ix = 0;
pif = (USBH_InterfaceDescTypeDef *)0;
pcfg = &phost->device.CfgDesc;
while (if_ix < USBH_MAX_NUM_INTERFACES)
{
pif = &pcfg->Itf_Desc[if_ix];
if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings))
{
return if_ix;
}
if_ix++;
}
return 0xFF;
}
/**
* @brief USBH_Start
* Start the USB Host Core.
* @param phost: Host Handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost)
{
/* Start the low level driver */
USBH_LL_Start(phost);
/* Activate VBUS on the port */
USBH_LL_DriverVBUS (phost, TRUE);
return USBH_OK;
}
/**
* @brief USBH_Stop
* Stop the USB Host Core.
* @param phost: Host Handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost)
{
/* Stop and cleanup the low level driver */
USBH_LL_Stop(phost);
/* DeActivate VBUS on the port */
USBH_LL_DriverVBUS (phost, FALSE);
/* FRee Control Pipes */
USBH_FreePipe (phost, phost->Control.pipe_in);
USBH_FreePipe (phost, phost->Control.pipe_out);
return USBH_OK;
}
/**
* @brief HCD_ReEnumerate
* Perform a new Enumeration phase.
* @param phost: Host Handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost)
{
/*Stop Host */
USBH_Stop(phost);
/*Device has disconnected, so wait for 200 ms */
USBH_Delay(200);
/* Set State machines in default state */
DeInitStateMachine(phost);
/* Start again the host */
USBH_Start(phost);
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
#endif
return USBH_OK;
}
/**
* @brief USBH_Process
* Background process of the USB Core.
* @param phost: Host Handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost)
{
__IO USBH_StatusTypeDef status = USBH_FAIL;
uint8_t idx = 0;
switch (phost->gState)
{
case HOST_IDLE :
if (phost->device.is_connected)
{
/* Wait for 200 ms after connection */
phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT;
USBH_Delay(200);
USBH_LL_ResetPort(phost);
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
#endif
}
break;
case HOST_DEV_WAIT_FOR_ATTACHMENT:
break;
case HOST_DEV_ATTACHED :
USBH_UsrLog("USB Device Attached");
/* Wait for 100 ms after Reset */
USBH_Delay(100);
phost->device.speed = USBH_LL_GetSpeed(phost);
phost->gState = HOST_ENUMERATION;
phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00);
phost->Control.pipe_in = USBH_AllocPipe (phost, 0x80);
/* Open Control pipes */
USBH_OpenPipe (phost,
phost->Control.pipe_in,
0x80,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
/* Open Control pipes */
USBH_OpenPipe (phost,
phost->Control.pipe_out,
0x00,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
#endif
break;
case HOST_ENUMERATION:
/* Check for enumeration status */
if ( USBH_HandleEnum(phost) == USBH_OK)
{
/* The function shall return USBH_OK when full enumeration is complete */
USBH_UsrLog ("Enumeration done.");
phost->device.current_interface = 0;
if(phost->device.DevDesc.bNumConfigurations == 1)
{
USBH_UsrLog ("This device has only 1 configuration.");
phost->gState = HOST_SET_CONFIGURATION;
}
else
{
phost->gState = HOST_INPUT;
}
}
break;
case HOST_INPUT:
{
/* user callback for end of device basic enumeration */
if(phost->pUser != NULL)
{
phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION);
phost->gState = HOST_SET_CONFIGURATION;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
}
break;
case HOST_SET_CONFIGURATION:
/* set configuration */
if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK)
{
phost->gState = HOST_CHECK_CLASS;
USBH_UsrLog ("Default configuration set.");
}
break;
case HOST_CHECK_CLASS:
if(phost->ClassNumber == 0)
{
USBH_UsrLog ("No Class has been registered.");
}
else
{
phost->pActiveClass = NULL;
for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++)
{
if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass)
{
phost->pActiveClass = phost->pClass[idx];
}
}
if(phost->pActiveClass != NULL)
{
if(phost->pActiveClass->Init(phost)== USBH_OK)
{
phost->gState = HOST_CLASS_REQUEST;
USBH_UsrLog ("%s class started.", phost->pActiveClass->Name);
/* Inform user that a class has been activated */
phost->pUser(phost, HOST_USER_CLASS_SELECTED);
}
else
{
phost->gState = HOST_ABORT_STATE;
USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name);
}
}
else
{
phost->gState = HOST_ABORT_STATE;
USBH_UsrLog ("No registered class for this device.");
}
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
break;
case HOST_CLASS_REQUEST:
/* process class standard control requests state machine */
if(phost->pActiveClass != NULL)
{
status = phost->pActiveClass->Requests(phost);
if(status == USBH_OK)
{
phost->gState = HOST_CLASS;
}
}
else
{
phost->gState = HOST_ABORT_STATE;
USBH_ErrLog ("Invalid Class Driver.");
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
break;
case HOST_CLASS:
/* process class state machine */
if(phost->pActiveClass != NULL)
{
phost->pActiveClass->BgndProcess(phost);
}
break;
case HOST_DEV_DISCONNECTED :
DeInitStateMachine(phost);
/* Re-Initilaize Host for new Enumeration */
if(phost->pActiveClass != NULL)
{
phost->pActiveClass->DeInit(phost);
phost->pActiveClass = NULL;
}
break;
case HOST_ABORT_STATE:
default :
break;
}
return USBH_OK;
}
/**
* @brief USBH_HandleEnum
* This function includes the complete enumeration process
* @param phost: Host Handle
* @retval USBH_Status
*/
static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef Status = USBH_BUSY;
switch (phost->EnumState)
{
case ENUM_IDLE:
/* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */
if ( USBH_Get_DevDesc(phost, 8) == USBH_OK)
{
phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize;
phost->EnumState = ENUM_GET_FULL_DEV_DESC;
/* modify control channels configuration for MaxPacket size */
USBH_OpenPipe (phost,
phost->Control.pipe_in,
0x80,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
/* Open Control pipes */
USBH_OpenPipe (phost,
phost->Control.pipe_out,
0x00,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
}
break;
case ENUM_GET_FULL_DEV_DESC:
/* Get FULL Device Desc */
if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK)
{
USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct );
USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor );
phost->EnumState = ENUM_SET_ADDR;
}
break;
case ENUM_SET_ADDR:
/* set address */
if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK)
{
USBH_Delay(2);
phost->device.address = USBH_DEVICE_ADDRESS;
/* user callback for device address assigned */
USBH_UsrLog("Address (#%d) assigned.", phost->device.address);
phost->EnumState = ENUM_GET_CFG_DESC;
/* modify control channels to update device address */
USBH_OpenPipe (phost,
phost->Control.pipe_in,
0x80,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
/* Open Control pipes */
USBH_OpenPipe (phost,
phost->Control.pipe_out,
0x00,
phost->device.address,
phost->device.speed,
USBH_EP_CONTROL,
phost->Control.pipe_size);
}
break;
case ENUM_GET_CFG_DESC:
/* get standard configuration descriptor */
if ( USBH_Get_CfgDesc(phost,
USB_CONFIGURATION_DESC_SIZE) == USBH_OK)
{
phost->EnumState = ENUM_GET_FULL_CFG_DESC;
}
break;
case ENUM_GET_FULL_CFG_DESC:
/* get FULL config descriptor (config, interface, endpoints) */
if (USBH_Get_CfgDesc(phost,
phost->device.CfgDesc.wTotalLength) == USBH_OK)
{
phost->EnumState = ENUM_GET_MFC_STRING_DESC;
}
break;
case ENUM_GET_MFC_STRING_DESC:
if (phost->device.DevDesc.iManufacturer != 0)
{ /* Check that Manufacturer String is available */
if ( USBH_Get_StringDesc(phost,
phost->device.DevDesc.iManufacturer,
phost->device.Data ,
0xff) == USBH_OK)
{
/* User callback for Manufacturing string */
USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data);
phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
}
else
{
USBH_UsrLog("Manufacturer : N/A");
phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
break;
case ENUM_GET_PRODUCT_STRING_DESC:
if (phost->device.DevDesc.iProduct != 0)
{ /* Check that Product string is available */
if ( USBH_Get_StringDesc(phost,
phost->device.DevDesc.iProduct,
phost->device.Data,
0xff) == USBH_OK)
{
/* User callback for Product string */
USBH_UsrLog("Product : %s", (char *)phost->device.Data);
phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
}
}
else
{
USBH_UsrLog("Product : N/A");
phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
break;
case ENUM_GET_SERIALNUM_STRING_DESC:
if (phost->device.DevDesc.iSerialNumber != 0)
{ /* Check that Serial number string is available */
if ( USBH_Get_StringDesc(phost,
phost->device.DevDesc.iSerialNumber,
phost->device.Data,
0xff) == USBH_OK)
{
/* User callback for Serial number string */
USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data);
Status = USBH_OK;
}
}
else
{
USBH_UsrLog("Serial Number : N/A");
Status = USBH_OK;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
#endif
}
break;
default:
break;
}
return Status;
}
/**
* @brief USBH_LL_SetTimer
* Set the initial Host Timer tick
* @param phost: Host Handle
* @retval None
*/
void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t time)
{
phost->Timer = time;
}
/**
* @brief USBH_LL_IncTimer
* Increment Host Timer tick
* @param phost: Host Handle
* @retval None
*/
void USBH_LL_IncTimer (USBH_HandleTypeDef *phost)
{
phost->Timer ++;
USBH_HandleSof(phost);
}
/**
* @brief USBH_HandleSof
* Call SOF process
* @param phost: Host Handle
* @retval None
*/
void USBH_HandleSof (USBH_HandleTypeDef *phost)
{
if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL))
{
phost->pActiveClass->SOFProcess(phost);
}
}
/**
* @brief USBH_LL_Connect
* Handle USB Host connexion event
* @param phost: Host Handle
* @retval USBH_Status
*/
USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost)
{
if(phost->gState == HOST_IDLE )
{
phost->device.is_connected = 1;
if(phost->pUser != NULL)
{
phost->pUser(phost, HOST_USER_CONNECTION);
}
}
else if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT )
{
phost->gState = HOST_DEV_ATTACHED ;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
#endif
return USBH_OK;
}
/**
* @brief USBH_LL_Disconnect
* Handle USB Host disconnection event
* @param phost: Host Handle
* @retval USBH_Status
*/
USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost)
{
/*Stop Host */
USBH_LL_Stop(phost);
/* FRee Control Pipes */
USBH_FreePipe (phost, phost->Control.pipe_in);
USBH_FreePipe (phost, phost->Control.pipe_out);
phost->device.is_connected = 0;
if(phost->pUser != NULL)
{
phost->pUser(phost, HOST_USER_DISCONNECTION);
}
USBH_UsrLog("USB Device disconnected");
/* Start the low level driver */
USBH_LL_Start(phost);
phost->gState = HOST_DEV_DISCONNECTED;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
#endif
return USBH_OK;
}
#if (USBH_USE_OS == 1)
/**
* @brief USB Host Thread task
* @param pvParameters not used
* @retval None
*/
static void USBH_Process_OS(void const * argument)
{
osEvent event;
for(;;)
{
event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever );
if( event.status == osEventMessage )
{
USBH_Process((USBH_HandleTypeDef *)argument);
}
}
}
/**
* @brief USBH_LL_NotifyURBChange
* Notify URB state Change
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost)
{
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
return USBH_OK;
}
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,881 @@
/**
******************************************************************************
* @file usbh_ctlreq.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements the control requests for device enumeration
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_ctlreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_CTLREQ
* @brief This file implements the standard requests for device enumeration
* @{
*/
/** @defgroup USBH_CTLREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost);
static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length);
static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
uint8_t *buf,
uint16_t length);
static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf);
static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length);
static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf);
/**
* @}
*/
/** @defgroup USBH_CTLREQ_Private_Functions
* @{
*/
/**
* @brief USBH_Get_DevDesc
* Issue Get Device Descriptor command to the device. Once the response
* received, it parses the device descriptor and updates the status.
* @param phost: Host Handle
* @param length: Length of the descriptor
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length)
{
USBH_StatusTypeDef status;
if((status = USBH_GetDescriptor(phost,
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
USB_DESC_DEVICE,
phost->device.Data,
length)) == USBH_OK)
{
/* Commands successfully sent and Response Received */
USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length);
}
return status;
}
/**
* @brief USBH_Get_CfgDesc
* Issues Configuration Descriptor to the device. Once the response
* received, it parses the configuration descriptor and updates the
* status.
* @param phost: Host Handle
* @param length: Length of the descriptor
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,
uint16_t length)
{
USBH_StatusTypeDef status;
uint8_t *pData;
#if (USBH_KEEP_CFG_DESCRIPTOR == 1)
pData = phost->device.CfgDesc_Raw;
#else
pData = phost->device.Data;
#endif
if((status = USBH_GetDescriptor(phost,
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
USB_DESC_CONFIGURATION,
pData,
length)) == USBH_OK)
{
/* Commands successfully sent and Response Received */
USBH_ParseCfgDesc (&phost->device.CfgDesc,
pData,
length);
}
return status;
}
/**
* @brief USBH_Get_StringDesc
* Issues string Descriptor command to the device. Once the response
* received, it parses the string descriptor and updates the status.
* @param phost: Host Handle
* @param string_index: String index for the descriptor
* @param buff: Buffer address for the descriptor
* @param length: Length of the descriptor
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost,
uint8_t string_index,
uint8_t *buff,
uint16_t length)
{
USBH_StatusTypeDef status;
if((status = USBH_GetDescriptor(phost,
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
USB_DESC_STRING | string_index,
phost->device.Data,
length)) == USBH_OK)
{
/* Commands successfully sent and Response Received */
USBH_ParseStringDesc(phost->device.Data,buff, length);
}
return status;
}
/**
* @brief USBH_GetDescriptor
* Issues Descriptor command to the device. Once the response received,
* it parses the descriptor and updates the status.
* @param phost: Host Handle
* @param req_type: Descriptor type
* @param value_idx: Value for the GetDescriptr request
* @param buff: Buffer to store the descriptor
* @param length: Length of the descriptor
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost,
uint8_t req_type,
uint16_t value_idx,
uint8_t* buff,
uint16_t length )
{
if(phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_D2H | req_type;
phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
phost->Control.setup.b.wValue.w = value_idx;
if ((value_idx & 0xff00) == USB_DESC_STRING)
{
phost->Control.setup.b.wIndex.w = 0x0409;
}
else
{
phost->Control.setup.b.wIndex.w = 0;
}
phost->Control.setup.b.wLength.w = length;
}
return USBH_CtlReq(phost, buff , length );
}
/**
* @brief USBH_SetAddress
* This command sets the address to the connected device
* @param phost: Host Handle
* @param DeviceAddress: Device address to assign
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost,
uint8_t DeviceAddress)
{
if(phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \
USB_REQ_TYPE_STANDARD;
phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS;
phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_SetCfg
* The command sets the configuration value to the connected device
* @param phost: Host Handle
* @param cfg_idx: Configuration value
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost,
uint16_t cfg_idx)
{
if(phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\
USB_REQ_TYPE_STANDARD;
phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
phost->Control.setup.b.wValue.w = cfg_idx;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_SetInterface
* The command sets the Interface value to the connected device
* @param phost: Host Handle
* @param altSetting: Interface value
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost,
uint8_t ep_num, uint8_t altSetting)
{
if(phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
USB_REQ_TYPE_STANDARD;
phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE;
phost->Control.setup.b.wValue.w = altSetting;
phost->Control.setup.b.wIndex.w = ep_num;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_ClrFeature
* This request is used to clear or disable a specific feature.
* @param phost: Host Handle
* @param ep_num: endpoint number
* @param hc_num: Host channel number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost,
uint8_t ep_num)
{
if(phost->RequestState == CMD_SEND)
{
phost->Control.setup.b.bmRequestType = USB_H2D |
USB_REQ_RECIPIENT_ENDPOINT |
USB_REQ_TYPE_STANDARD;
phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
phost->Control.setup.b.wIndex.w = ep_num;
phost->Control.setup.b.wLength.w = 0;
}
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_ParseDevDesc
* This function Parses the device descriptor
* @param dev_desc: device_descriptor destination address
* @param buf: Buffer where the source descriptor is available
* @param length: Length of the descriptor
* @retval None
*/
static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc,
uint8_t *buf,
uint16_t length)
{
dev_desc->bLength = *(uint8_t *) (buf + 0);
dev_desc->bDescriptorType = *(uint8_t *) (buf + 1);
dev_desc->bcdUSB = LE16 (buf + 2);
dev_desc->bDeviceClass = *(uint8_t *) (buf + 4);
dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5);
dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6);
dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7);
if (length > 8)
{ /* For 1st time after device connection, Host may issue only 8 bytes for
Device Descriptor Length */
dev_desc->idVendor = LE16 (buf + 8);
dev_desc->idProduct = LE16 (buf + 10);
dev_desc->bcdDevice = LE16 (buf + 12);
dev_desc->iManufacturer = *(uint8_t *) (buf + 14);
dev_desc->iProduct = *(uint8_t *) (buf + 15);
dev_desc->iSerialNumber = *(uint8_t *) (buf + 16);
dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17);
}
}
/**
* @brief USBH_ParseCfgDesc
* This function Parses the configuration descriptor
* @param cfg_desc: Configuration Descriptor address
* @param buf: Buffer where the source descriptor is available
* @param length: Length of the descriptor
* @retval None
*/
static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
uint8_t *buf,
uint16_t length)
{
USBH_InterfaceDescTypeDef *pif ;
USBH_EpDescTypeDef *pep;
USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf;
uint16_t ptr;
int8_t if_ix = 0;
int8_t ep_ix = 0;
pdesc = (USBH_DescHeader_t *)buf;
/* Parse configuration descriptor */
cfg_desc->bLength = *(uint8_t *) (buf + 0);
cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1);
cfg_desc->wTotalLength = LE16 (buf + 2);
cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4);
cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5);
cfg_desc->iConfiguration = *(uint8_t *) (buf + 6);
cfg_desc->bmAttributes = *(uint8_t *) (buf + 7);
cfg_desc->bMaxPower = *(uint8_t *) (buf + 8);
if (length > USB_CONFIGURATION_DESC_SIZE)
{
ptr = USB_LEN_CFG_DESC;
pif = (USBH_InterfaceDescTypeDef *)0;
while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength))
{
pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE)
{
pif = &cfg_desc->Itf_Desc[if_ix];
USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc);
ep_ix = 0;
pep = (USBH_EpDescTypeDef *)0;
while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength))
{
pdesc = USBH_GetNextDesc((uint8_t*) pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
{
pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix];
USBH_ParseEPDesc (pep, (uint8_t *)pdesc);
ep_ix++;
}
}
if_ix++;
}
}
}
}
/**
* @brief USBH_ParseInterfaceDesc
* This function Parses the interface descriptor
* @param if_descriptor : Interface descriptor destination
* @param buf: Buffer where the descriptor data is available
* @retval None
*/
static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor,
uint8_t *buf)
{
if_descriptor->bLength = *(uint8_t *) (buf + 0);
if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2);
if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3);
if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4);
if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5);
if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6);
if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7);
if_descriptor->iInterface = *(uint8_t *) (buf + 8);
}
/**
* @brief USBH_ParseEPDesc
* This function Parses the endpoint descriptor
* @param ep_descriptor: Endpoint descriptor destination address
* @param buf: Buffer where the parsed descriptor stored
* @retval None
*/
static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor,
uint8_t *buf)
{
ep_descriptor->bLength = *(uint8_t *) (buf + 0);
ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2);
ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3);
ep_descriptor->wMaxPacketSize = LE16 (buf + 4);
ep_descriptor->bInterval = *(uint8_t *) (buf + 6);
}
/**
* @brief USBH_ParseStringDesc
* This function Parses the string descriptor
* @param psrc: Source pointer containing the descriptor data
* @param pdest: Destination address pointer
* @param length: Length of the descriptor
* @retval None
*/
static void USBH_ParseStringDesc (uint8_t* psrc,
uint8_t* pdest,
uint16_t length)
{
uint16_t strlength;
uint16_t idx;
/* The UNICODE string descriptor is not NULL-terminated. The string length is
computed by substracting two from the value of the first byte of the descriptor.
*/
/* Check which is lower size, the Size of string or the length of bytes read
from the device */
if ( psrc[1] == USB_DESC_TYPE_STRING)
{ /* Make sure the Descriptor is String Type */
/* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length);
psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */
for (idx = 0; idx < strlength; idx+=2 )
{/* Copy Only the string and ignore the UNICODE ID, hence add the src */
*pdest = psrc[idx];
pdest++;
}
*pdest = 0; /* mark end of string */
}
}
/**
* @brief USBH_GetNextDesc
* This function return the next descriptor header
* @param buf: Buffer where the cfg descriptor is available
* @param ptr: data pointer inside the cfg descriptor
* @retval next header
*/
USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr)
{
USBH_DescHeader_t *pnext;
*ptr += ((USBH_DescHeader_t *)pbuf)->bLength;
pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \
((USBH_DescHeader_t *)pbuf)->bLength);
return(pnext);
}
/**
* @brief USBH_CtlReq
* USBH_CtlReq sends a control request and provide the status after
* completion of the request
* @param phost: Host Handle
* @param req: Setup Request Structure
* @param buff: data buffer address to store the response
* @param length: length of the response
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length)
{
USBH_StatusTypeDef status;
status = USBH_BUSY;
switch (phost->RequestState)
{
case CMD_SEND:
/* Start a SETUP transfer */
phost->Control.buff = buff;
phost->Control.length = length;
phost->Control.state = CTRL_SETUP;
phost->RequestState = CMD_WAIT;
status = USBH_BUSY;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
break;
case CMD_WAIT:
status = USBH_HandleControl(phost);
if (status == USBH_OK)
{
/* Commands successfully sent and Response Received */
phost->RequestState = CMD_SEND;
phost->Control.state =CTRL_IDLE;
status = USBH_OK;
}
else if (status == USBH_FAIL)
{
/* Failure Mode */
phost->RequestState = CMD_SEND;
status = USBH_FAIL;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_HandleControl
* Handles the USB control transfer state machine
* @param phost: Host Handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost)
{
uint8_t direction;
USBH_StatusTypeDef status = USBH_BUSY;
USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
switch (phost->Control.state)
{
case CTRL_SETUP:
/* send a SETUP packet */
USBH_CtlSendSetup (phost,
(uint8_t *)phost->Control.setup.d8 ,
phost->Control.pipe_out);
phost->Control.state = CTRL_SETUP_WAIT;
break;
case CTRL_SETUP_WAIT:
URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out);
/* case SETUP packet sent successfully */
if(URB_Status == USBH_URB_DONE)
{
direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK);
/* check if there is a data stage */
if (phost->Control.setup.b.wLength.w != 0 )
{
if (direction == USB_D2H)
{
/* Data Direction is IN */
phost->Control.state = CTRL_DATA_IN;
}
else
{
/* Data Direction is OUT */
phost->Control.state = CTRL_DATA_OUT;
}
}
/* No DATA stage */
else
{
/* If there is No Data Transfer Stage */
if (direction == USB_D2H)
{
/* Data Direction is IN */
phost->Control.state = CTRL_STATUS_OUT;
}
else
{
/* Data Direction is OUT */
phost->Control.state = CTRL_STATUS_IN;
}
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
break;
case CTRL_DATA_IN:
/* Issue an IN token */
phost->Control.timer = phost->Timer;
USBH_CtlReceiveData(phost,
phost->Control.buff,
phost->Control.length,
phost->Control.pipe_in);
phost->Control.state = CTRL_DATA_IN_WAIT;
break;
case CTRL_DATA_IN_WAIT:
URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
/* check is DATA packet transferred successfully */
if (URB_Status == USBH_URB_DONE)
{
phost->Control.state = CTRL_STATUS_OUT;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
/* manage error cases*/
if (URB_Status == USBH_URB_STALL)
{
/* In stall case, return to previous machine state*/
status = USBH_NOT_SUPPORTED;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_ERROR)
{
/* Device error */
phost->Control.state = CTRL_ERROR;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
break;
case CTRL_DATA_OUT:
USBH_CtlSendData (phost,
phost->Control.buff,
phost->Control.length ,
phost->Control.pipe_out,
1);
phost->Control.timer = phost->Timer;
phost->Control.state = CTRL_DATA_OUT_WAIT;
break;
case CTRL_DATA_OUT_WAIT:
URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
if (URB_Status == USBH_URB_DONE)
{ /* If the Setup Pkt is sent successful, then change the state */
phost->Control.state = CTRL_STATUS_IN;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
/* handle error cases */
else if (URB_Status == USBH_URB_STALL)
{
/* In stall case, return to previous machine state*/
phost->Control.state = CTRL_STALLED;
status = USBH_NOT_SUPPORTED;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_NOTREADY)
{
/* Nack received from device */
phost->Control.state = CTRL_DATA_OUT;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_ERROR)
{
/* device error */
phost->Control.state = CTRL_ERROR;
status = USBH_FAIL;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
break;
case CTRL_STATUS_IN:
/* Send 0 bytes out packet */
USBH_CtlReceiveData (phost,
0,
0,
phost->Control.pipe_in);
phost->Control.timer = phost->Timer;
phost->Control.state = CTRL_STATUS_IN_WAIT;
break;
case CTRL_STATUS_IN_WAIT:
URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
if ( URB_Status == USBH_URB_DONE)
{ /* Control transfers completed, Exit the State Machine */
phost->Control.state = CTRL_COMPLETE;
status = USBH_OK;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
/* Control transfers completed, Exit the State Machine */
status = USBH_NOT_SUPPORTED;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
break;
case CTRL_STATUS_OUT:
USBH_CtlSendData (phost,
0,
0,
phost->Control.pipe_out,
1);
phost->Control.timer = phost->Timer;
phost->Control.state = CTRL_STATUS_OUT_WAIT;
break;
case CTRL_STATUS_OUT_WAIT:
URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
if (URB_Status == USBH_URB_DONE)
{
status = USBH_OK;
phost->Control.state = CTRL_COMPLETE;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_NOTREADY)
{
phost->Control.state = CTRL_STATUS_OUT;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
else if (URB_Status == USBH_URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
#endif
}
break;
case CTRL_ERROR:
/*
After a halt condition is encountered or an error is detected by the
host, a control endpoint is allowed to recover by accepting the next Setup
PID; i.e., recovery actions via some other pipe are not required for control
endpoints. For the Default Control Pipe, a device reset will ultimately be
required to clear the halt or error condition if the next Setup PID is not
accepted.
*/
if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT)
{
/* try to recover control */
USBH_LL_Stop(phost);
/* Do the transmission again, starting from SETUP Packet */
phost->Control.state = CTRL_SETUP;
phost->RequestState = CMD_SEND;
}
else
{
phost->pUser(phost, HOST_USER_UNRECOVERED_ERROR);
phost->Control.errorcount = 0;
USBH_ErrLog("Control error");
status = USBH_FAIL;
}
break;
default:
break;
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,358 @@
/**
******************************************************************************
* @file usbh_ioreq.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file handles the issuing of the USB transactions
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_ioreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_IOREQ
* @brief This file handles the standard protocol processing (USB v2.0)
* @{
*/
/** @defgroup USBH_IOREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Functions
* @{
*/
/**
* @brief USBH_CtlSendSetup
* Sends the Setup Packet to the Device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be send to Device
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_CONTROL, /* EP type */
USBH_PID_SETUP, /* Type setup */
buff, /* data buffer */
USBH_SETUP_PKT_SIZE, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_CtlSendData
* Sends a data Packet to the Device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be sent to Device
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num,
uint8_t do_ping )
{
if(phost->device.speed != USBH_SPEED_HIGH)
{
do_ping = 0;
}
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_CONTROL, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
do_ping); /* do ping (HS Only)*/
return USBH_OK;
}
/**
* @brief USBH_CtlReceiveData
* Receives the Device Response to the Setup Packet
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost,
uint8_t* buff,
uint16_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_CONTROL, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_BulkSendData
* Sends the Bulk Packet to the device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be sent to Device
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num,
uint8_t do_ping )
{
if(phost->device.speed != USBH_SPEED_HIGH)
{
do_ping = 0;
}
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : IN */
USBH_EP_BULK, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
do_ping); /* do ping (HS Only)*/
return USBH_OK;
}
/**
* @brief USBH_BulkReceiveData
* Receives IN bulk packet from device
* @param phost: Host Handle
* @param buff: Buffer pointer in which the received data packet to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_BULK, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_InterruptReceiveData
* Receives the Device Response to the Interrupt IN token
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_INTERRUPT, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_InterruptSendData
* Sends the data on Interrupt OUT Endpoint
* @param phost: Host Handle
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_INTERRUPT, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_IsocReceiveData
* Receives the Device Response to the Isochronous IN token
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_ISO, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_IsocSendData
* Sends the data on Isochronous OUT Endpoint
* @param phost: Host Handle
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_ISO, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,204 @@
/**
******************************************************************************
* @file usbh_pipes.c
* @author MCD Application Team
* @version V3.2.2
* @date 07-July-2015
* @brief This file implements functions for opening and closing Pipes
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 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_pipes.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_PIPES
* @brief This file includes opening and closing Pipes
* @{
*/
/** @defgroup USBH_PIPES_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Functions
* @{
*/
static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost);
/**
* @brief USBH_Open_Pipe
* Open a pipe
* @param phost: Host Handle
* @param pipe_num: Pipe Number
* @param dev_address: USB Device address allocated to attached device
* @param speed : USB device speed (Full/Low)
* @param ep_type: end point type (Bulk/int/ctl)
* @param mps: max pkt size
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
USBH_LL_OpenPipe(phost,
pipe_num,
epnum,
dev_address,
speed,
ep_type,
mps);
return USBH_OK;
}
/**
* @brief USBH_ClosePipe
* Close a pipe
* @param phost: Host Handle
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num)
{
USBH_LL_ClosePipe(phost, pipe_num);
return USBH_OK;
}
/**
* @brief USBH_Alloc_Pipe
* Allocate a new Pipe
* @param phost: Host Handle
* @param ep_addr: End point for which the Pipe to be allocated
* @retval Pipe number
*/
uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr)
{
uint16_t pipe;
pipe = USBH_GetFreePipe(phost);
if (pipe != 0xFFFF)
{
phost->Pipes[pipe] = 0x8000 | ep_addr;
}
return pipe;
}
/**
* @brief USBH_Free_Pipe
* Free the USB Pipe
* @param phost: Host Handle
* @param idx: Pipe number to be freed
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx)
{
if(idx < 11)
{
phost->Pipes[idx] &= 0x7FFF;
}
return USBH_OK;
}
/**
* @brief USBH_GetFreePipe
* @param phost: Host Handle
* Get a free Pipe number for allocation to a device endpoint
* @retval idx: Free Pipe number
*/
static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost)
{
uint8_t idx = 0;
for (idx = 0 ; idx < 11 ; idx++)
{
if ((phost->Pipes[idx] & 0x8000) == 0)
{
return idx;
}
}
return 0xFFFF;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/