diff options
Diffstat (limited to 'stmhal/usbhost/Class')
25 files changed, 13619 insertions, 0 deletions
diff --git a/stmhal/usbhost/Class/AUDIO/Inc/usbh_audio.h b/stmhal/usbhost/Class/AUDIO/Inc/usbh_audio.h new file mode 100644 index 000000000..8cee530d0 --- /dev/null +++ b/stmhal/usbhost/Class/AUDIO/Inc/usbh_audio.h @@ -0,0 +1,581 @@ +/**
+ ******************************************************************************
+ * @file usbh_audio.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_audio.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_AUDIO_H
+#define __USBH_AUDIO_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_AUDIO_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_AUDIO_CORE
+ * @brief This file is the Header file for usbh_audio.c
+ * @{
+ */
+
+
+/** @defgroup USBH_AUDIO_CORE_Exported_Types
+ * @{
+ */
+
+/* States for AUDIO State Machine */
+typedef enum
+{
+ AUDIO_INIT = 0,
+ AUDIO_IDLE,
+ AUDIO_CS_REQUESTS,
+ AUDIO_SET_DEFAULT_FEATURE_UNIT,
+ AUDIO_SET_INTERFACE,
+ AUDIO_SET_STREAMING_INTERFACE,
+ AUDIO_SET_CUR1,
+ AUDIO_GET_MIN,
+ AUDIO_GET_MAX,
+ AUDIO_GET_RES,
+ AUDIO_GET_CUR1,
+ AUDIO_SET_CUR2,
+ AUDIO_GET_CUR2,
+ AUDIO_SET_CUR3,
+ AUDIO_SET_INTERFACE0,
+ AUDIO_SET_INTERFACE1,
+ AUDIO_SET_INTERFACE2,
+ AUDIO_ISOC_OUT,
+ AUDIO_ISOC_IN,
+ AUDIO_ISOC_POLL,
+ AUDIO_ERROR,
+}
+AUDIO_StateTypeDef;
+
+typedef enum
+{
+ AUDIO_REQ_INIT = 1,
+ AUDIO_REQ_IDLE,
+ AUDIO_REQ_SET_DEFAULT_IN_INTERFACE,
+ AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE,
+ AUDIO_REQ_SET_IN_INTERFACE,
+ AUDIO_REQ_SET_OUT_INTERFACE,
+ AUDIO_REQ_CS_REQUESTS,
+}
+AUDIO_ReqStateTypeDef;
+
+typedef enum
+{
+ AUDIO_REQ_SET_VOLUME = 1,
+ AUDIO_REQ_SET_MUTE,
+ AUDIO_REQ_GET_CURR_VOLUME,
+ AUDIO_REQ_GET_MIN_VOLUME,
+ AUDIO_REQ_GET_MAX_VOLUME,
+ AUDIO_REQ_GET_VOLUME,
+ AUDIO_REQ_GET_RESOLUTION,
+ AUDIO_REQ_CS_IDLE,
+}
+AUDIO_CSReqStateTypeDef;
+
+typedef enum
+{
+ AUDIO_PLAYBACK_INIT = 1,
+ AUDIO_PLAYBACK_SET_EP,
+ AUDIO_PLAYBACK_SET_EP_FREQ,
+ AUDIO_PLAYBACK_PLAY,
+ AUDIO_PLAYBACK_IDLE,
+}
+AUDIO_PlayStateTypeDef;
+
+typedef enum
+{
+ VOLUME_UP = 1,
+ VOLUME_DOWN = 2,
+}
+AUDIO_VolumeCtrlTypeDef;
+
+typedef enum
+{
+ AUDIO_CONTROL_INIT = 1,
+ AUDIO_CONTROL_CHANGE,
+ AUDIO_CONTROL_IDLE,
+ AUDIO_CONTROL_VOLUME_UP,
+ AUDIO_CONTROL_VOLUME_DOWN,
+}
+AUDIO_ControlStateTypeDef;
+
+
+typedef enum
+{
+ AUDIO_DATA_START_OUT = 1,
+ AUDIO_DATA_OUT,
+}
+AUDIO_ProcessingTypeDef;
+
+/* Structure for AUDIO process */
+typedef struct
+{
+ uint8_t Channels;
+ uint8_t Bits;
+ uint32_t SampleRate;
+}
+AUDIO_FormatTypeDef;
+
+typedef struct
+{
+ uint8_t Ep;
+ uint16_t EpSize;
+ uint8_t AltSettings;
+ uint8_t interface;
+ uint8_t valid;
+ uint16_t Poll;
+}
+AUDIO_STREAMING_IN_HandleTypeDef;
+
+typedef struct
+{
+ uint8_t Ep;
+ uint16_t EpSize;
+ uint8_t AltSettings;
+ uint8_t interface;
+ uint8_t valid;
+ uint16_t Poll;
+}
+AUDIO_STREAMING_OUT_HandleTypeDef;
+
+
+typedef struct
+{
+ uint8_t mute;
+ uint32_t volumeMin;
+ uint32_t volumeMax;
+ uint32_t volume;
+ uint32_t resolution;
+}
+AUDIO_ControlAttributeTypeDef;
+
+typedef struct
+{
+
+ uint8_t Ep;
+ uint16_t EpSize;
+ uint8_t interface;
+ uint8_t AltSettings;
+ uint8_t supported;
+
+ uint8_t Pipe;
+ uint8_t Poll;
+ uint32_t timer ;
+
+ uint8_t asociated_as;
+ uint8_t asociated_mixer;
+ uint8_t asociated_selector;
+ uint8_t asociated_feature;
+ uint8_t asociated_terminal;
+ uint8_t asociated_channels;
+
+ uint32_t frequency;
+ uint8_t *buf;
+ uint8_t *cbuf;
+ uint32_t partial_ptr;
+
+ uint32_t global_ptr;
+ uint16_t frame_length;
+ uint32_t total_length;
+
+ AUDIO_ControlAttributeTypeDef attribute;
+}
+AUDIO_InterfaceStreamPropTypeDef;
+
+typedef struct
+{
+
+ uint8_t Ep;
+ uint16_t EpSize;
+ uint8_t interface;
+ uint8_t supported;
+
+ uint8_t Pipe;
+ uint8_t Poll;
+ uint32_t timer ;
+}
+AUDIO_InterfaceControlPropTypeDef;
+
+
+#define AUDIO_MAX_AUDIO_STD_INTERFACE 0x05
+#define AUDIO_MAX_FREQ_SUPPORTED 0x05
+#define AUDIO_MAX_STREAMING_INTERFACE 0x05
+#define AUDIO_MAX_NUM_IN_TERMINAL 0x04
+#define AUDIO_MAX_NUM_OUT_TERMINAL 0x04
+#define AUDIO_MAX_NUM_FEATURE_UNIT 0x04
+#define AUDIO_MAX_NUM_MIXER_UNIT 0x04
+#define AUDIO_MAX_NUM_SELECTOR_UNIT 0x04
+
+#define HEADPHONE_SUPPORTED 0x01
+#define MICROPHONE_SUPPORTED 0x02
+#define HEADSET_SUPPORTED 0x03
+
+
+/*Class-Specific AS(Audio Streaming) Interface Descriptor*/
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalLink;
+ uint8_t bDelay;
+ uint8_t wFormatTag[2];
+}
+AUDIO_ASGeneralDescTypeDef;
+
+/*Class-Specific AS(Audio Streaming) Format Type Descriptor*/
+typedef struct
+{
+ uint8_t bLength; /*At to be deside*/
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bFormatType;
+ uint8_t bNrChannels;
+ uint8_t bSubframeSize;
+ uint8_t bBitResolution;
+ uint8_t bSamFreqType;
+ uint8_t tSamFreq[][3];
+}
+AUDIO_ASFormatTypeDescTypeDef;
+
+/*Class-Specific AS(Audio Streaming) Interface Descriptor*/
+typedef struct
+{
+ AUDIO_ASGeneralDescTypeDef *GeneralDesc;
+ AUDIO_ASFormatTypeDescTypeDef *FormatTypeDesc;
+}
+AUDIO_ASDescTypeDef;
+
+/* 4.3.2 Class-Specific AC Interface Descriptor */
+
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bcdADC[2];
+ uint8_t wTotalLength[2];
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+}
+AUDIO_HeaderDescTypeDef;
+
+/* 4.3.2.1 Input Terminal Descriptor */
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint8_t wTerminalType[2];
+ uint8_t bAssocTerminal;
+ uint8_t bNrChannels;
+ uint8_t wChannelConfig[2];
+ uint8_t iChannelNames;
+ uint8_t iTerminal;
+}
+AUDIO_ITDescTypeDef;
+
+/* 4.3.2.2 Output Terminal Descriptor */
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint8_t wTerminalType[2];
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+}
+AUDIO_OTDescTypeDef;
+
+/* 4.3.2.3 Feature Descriptor */
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint8_t bControlSize;
+ uint8_t bmaControls[][2];
+}
+AUDIO_FeatureDescTypeDef;
+
+
+/* 4.3.2.3 Feature Descriptor */
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bUnitID;
+ uint8_t bNrInPins;
+ uint8_t bSourceID0;
+ uint8_t bSourceID1;
+ uint8_t bNrChannels;
+ uint8_t bmChannelsConfig[2];
+ uint8_t iChannelsNames;
+ uint8_t bmaControls;
+ uint8_t iMixer;
+}
+AUDIO_MixerDescTypeDef;
+
+
+
+/* 4.3.2.3 Feature Descriptor */
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bUnitID;
+ uint8_t bNrInPins;
+ uint8_t bSourceID0;
+ uint8_t iSelector;
+}
+AUDIO_SelectorDescTypeDef;
+
+/*Class-Specific AC(Audio Control) Interface Descriptor*/
+typedef struct
+{
+ AUDIO_HeaderDescTypeDef *HeaderDesc;
+ AUDIO_ITDescTypeDef *InputTerminalDesc [AUDIO_MAX_NUM_IN_TERMINAL];
+ AUDIO_OTDescTypeDef *OutputTerminalDesc[AUDIO_MAX_NUM_OUT_TERMINAL];
+ AUDIO_FeatureDescTypeDef *FeatureUnitDesc [AUDIO_MAX_NUM_FEATURE_UNIT];
+ AUDIO_MixerDescTypeDef *MixerUnitDesc [AUDIO_MAX_NUM_MIXER_UNIT];
+ AUDIO_SelectorDescTypeDef *SelectorUnitDesc [AUDIO_MAX_NUM_SELECTOR_UNIT];
+}
+AUDIO_ACDescTypeDef;
+
+/*Class-Specific AC : Global descriptor*/
+
+typedef struct
+{
+ AUDIO_ACDescTypeDef cs_desc; /* Only one control descriptor*/
+ AUDIO_ASDescTypeDef as_desc[AUDIO_MAX_STREAMING_INTERFACE];
+
+ uint16_t ASNum;
+ uint16_t InputTerminalNum;
+ uint16_t OutputTerminalNum;
+ uint16_t FeatureUnitNum;
+ uint16_t SelectorUnitNum;
+ uint16_t MixerUnitNum;
+}
+AUDIO_ClassSpecificDescTypedef;
+
+
+typedef struct _AUDIO_Process
+{
+ AUDIO_ReqStateTypeDef req_state;
+ AUDIO_CSReqStateTypeDef cs_req_state;
+ AUDIO_PlayStateTypeDef play_state;
+ AUDIO_ControlStateTypeDef control_state;
+ AUDIO_ProcessingTypeDef processing_state;
+
+ AUDIO_STREAMING_IN_HandleTypeDef stream_in[AUDIO_MAX_AUDIO_STD_INTERFACE];
+ AUDIO_STREAMING_OUT_HandleTypeDef stream_out[AUDIO_MAX_AUDIO_STD_INTERFACE];
+ AUDIO_ClassSpecificDescTypedef class_desc;
+
+ AUDIO_InterfaceStreamPropTypeDef headphone;
+ AUDIO_InterfaceStreamPropTypeDef microphone;
+ AUDIO_InterfaceControlPropTypeDef control;
+ uint16_t mem [8];
+ uint8_t temp_feature;
+ uint8_t temp_channels;
+}
+AUDIO_HandleTypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Exported_Defines
+ * @{
+ */
+
+
+/*Audio Interface Subclass Codes*/
+#define AC_CLASS 0x01
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL 0x01
+#define USB_SUBCLASS_AUDIOSTREAMING 0x02
+#define USB_SUBCLASS_MIDISTREAMING 0x03
+
+#define USB_DESC_TYPE_CS_INTERFACE 0x24
+#define USB_DESC_TYPE_CS_ENDPOINT 0x25
+
+/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
+#define UAC_HEADER 0x01
+#define UAC_INPUT_TERMINAL 0x02
+#define UAC_OUTPUT_TERMINAL 0x03
+#define UAC_MIXER_UNIT 0x04
+#define UAC_SELECTOR_UNIT 0x05
+#define UAC_FEATURE_UNIT 0x06
+#define UAC_PROCESSING_UNIT 0x07
+#define UAC_EXTENSION_UNIT 0x08
+
+/*Audio Class-Specific Endpoint Descriptor Subtypes*/
+#define EP_CONTROL_UNDEFINED 0x00
+#define SAMPLING_FREQ_CONTROL 0x01
+#define PITCH_CONTROL 0x02
+
+/*Feature unit control selector*/
+#define FU_CONTROL_UNDEFINED 0x00
+#define MUTE_CONTROL 0x01
+#define VOLUME_CONTROL 0x02
+#define BASS_CONTROL 0x03
+#define MID_CONTROL 0x04
+#define TREBLE_CONTROL 0x05
+#define GRAPHIC_EQUALIZER_CONTROL 0x06
+#define AUTOMATIC_GAIN_CONTROL 0x07
+#define DELAY_CONTROL 0x08
+#define BASS_BOOST_CONTROL 0x09
+#define LOUDNESS_CONTROL 0x0A
+
+/*Terminal control selector*/
+#define TE_CONTROL_UNDEFINED 0x00
+#define COPY_PROTECT_CONTROL 0x01
+
+
+/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
+#define UAC_AS_GENERAL 0x01
+#define UAC_FORMAT_TYPE 0x02
+#define UAC_FORMAT_SPECIFIC 0x03
+
+/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_EP_GENERAL 0x01
+
+/* A.9 Audio Class-Specific Request Codes */
+#define UAC_SET_ 0x00
+#define UAC_GET_ 0x80
+
+#define UAC__CUR 0x1
+#define UAC__MIN 0x2
+#define UAC__MAX 0x3
+#define UAC__RES 0x4
+#define UAC__MEM 0x5
+
+#define UAC_SET_CUR (UAC_SET_ | UAC__CUR)
+#define UAC_GET_CUR (UAC_GET_ | UAC__CUR)
+#define UAC_SET_MIN (UAC_SET_ | UAC__MIN)
+#define UAC_GET_MIN (UAC_GET_ | UAC__MIN)
+#define UAC_SET_MAX (UAC_SET_ | UAC__MAX)
+#define UAC_GET_MAX (UAC_GET_ | UAC__MAX)
+#define UAC_SET_RES (UAC_SET_ | UAC__RES)
+#define UAC_GET_RES (UAC_GET_ | UAC__RES)
+#define UAC_SET_MEM (UAC_SET_ | UAC__MEM)
+#define UAC_GET_MEM (UAC_GET_ | UAC__MEM)
+
+#define UAC_GET_STAT 0xff
+
+/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
+#define UAC_MS_HEADER 0x01
+#define UAC_MIDI_IN_JACK 0x02
+#define UAC_MIDI_OUT_JACK 0x03
+
+/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_MS_GENERAL 0x01
+
+/* Terminals - 2.1 USB Terminal Types */
+#define UAC_TERMINAL_UNDEFINED 0x100
+#define UAC_TERMINAL_STREAMING 0x101
+#define UAC_TERMINAL_VENDOR_SPEC 0x1FF
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Exported_Variables
+ * @{
+ */
+extern USBH_ClassTypeDef AUDIO_Class;
+#define USBH_AUDIO_CLASS &AUDIO_Class
+/**
+ * @}
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Exported_FunctionsPrototype
+ * @{
+ */
+USBH_StatusTypeDef USBH_AUDIO_SetFrequency (USBH_HandleTypeDef *phost,
+ uint16_t sample_rate,
+ uint8_t channel_num,
+ uint8_t data_width);
+
+USBH_StatusTypeDef USBH_AUDIO_Play (USBH_HandleTypeDef *phost, uint8_t *buf, uint32_t length);
+USBH_StatusTypeDef USBH_AUDIO_Stop (USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_AUDIO_Suspend (USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_AUDIO_Resume (USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_AUDIO_SetVolume (USBH_HandleTypeDef *phost, AUDIO_VolumeCtrlTypeDef volume_ctl);
+USBH_StatusTypeDef USBH_AUDIO_ChangeOutBuffer (USBH_HandleTypeDef *phost, uint8_t *buf);
+int32_t USBH_AUDIO_GetOutOffset (USBH_HandleTypeDef *phost);
+
+void USBH_AUDIO_FrequencySet(USBH_HandleTypeDef *phost);
+/**
+ * @}
+ */
+
+
+#endif /* __USBH_AUDIO_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/AUDIO/Src/usbh_audio.c b/stmhal/usbhost/Class/AUDIO/Src/usbh_audio.c new file mode 100644 index 000000000..b9677b6c2 --- /dev/null +++ b/stmhal/usbhost/Class/AUDIO/Src/usbh_audio.c @@ -0,0 +1,1994 @@ +/**
+ ******************************************************************************
+ * @file usbh_audio.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the AC Layer Handlers for USB Host AC class.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_audio.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_AUDIO_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_AUDIO_CORE
+ * @brief This file includes HID Layer Handlers for USB Host HID class.
+ * @{
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_AUDIO_CORE_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_AUDIO_CORE_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_AUDIO_CORE_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_AUDIO_CORE_Private_FunctionPrototypes
+ * @{
+ */
+
+static USBH_StatusTypeDef USBH_AUDIO_InterfaceInit (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_InterfaceDeInit (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_Process(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_SOFProcess(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_ClassRequest(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_CSRequest(USBH_HandleTypeDef *phost,
+ uint8_t feature,
+ uint8_t channel);
+
+static USBH_StatusTypeDef USBH_AUDIO_HandleCSRequest(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingIN(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingOUT(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_FindHIDControl(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_ParseCSDescriptors(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_AUDIO_BuildHeadphonePath(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_BuildMicrophonePath(USBH_HandleTypeDef *phost);
+int32_t USBH_AUDIO_FindLinkedUnitIN(USBH_HandleTypeDef *phost, uint8_t UnitID);
+int32_t USBH_AUDIO_FindLinkedUnitOUT(USBH_HandleTypeDef *phost, uint8_t UnitID);
+
+
+
+static USBH_StatusTypeDef ParseCSDescriptors(AUDIO_ClassSpecificDescTypedef *class_desc,
+ uint8_t ac_subclass,
+ uint8_t *pdesc);
+
+
+static USBH_StatusTypeDef USBH_AUDIO_Transmit (USBH_HandleTypeDef *phost);
+
+
+static USBH_StatusTypeDef USBH_AC_SetCur(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length);
+
+static USBH_StatusTypeDef USBH_AC_GetCur(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length);
+
+static USBH_StatusTypeDef USBH_AC_GetMin(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length);
+
+static USBH_StatusTypeDef USBH_AC_GetMax(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length);
+
+static USBH_StatusTypeDef USBH_AC_GetRes(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length);
+
+static USBH_StatusTypeDef USBH_AUDIO_SetEndpointControls(USBH_HandleTypeDef *phost,
+ uint8_t Ep,
+ uint8_t *buff);
+
+static USBH_StatusTypeDef AUDIO_SetVolume (USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel, uint16_t volume);
+
+static USBH_StatusTypeDef USBH_AUDIO_InputStream (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_OutputStream (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_Control (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_AUDIO_SetControlAttribute (USBH_HandleTypeDef *phost, uint8_t attrib);
+static int32_t USBH_AUDIO_FindLinkedUnit(USBH_HandleTypeDef *phost, uint8_t UnitID);
+
+USBH_ClassTypeDef AUDIO_Class =
+{
+ "AUDIO",
+ AC_CLASS,
+ USBH_AUDIO_InterfaceInit,
+ USBH_AUDIO_InterfaceDeInit,
+ USBH_AUDIO_ClassRequest,
+ USBH_AUDIO_Process,
+ USBH_AUDIO_SOFProcess,
+ NULL,
+};
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_AUDIO_CORE_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBH_AUDIO_InterfaceInit
+ * The function init the Audio class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_InterfaceInit (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ USBH_StatusTypeDef out_status, in_status ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ uint8_t interface, index;
+ uint16_t ep_size_out = 0;
+ uint16_t ep_size_in = 0;
+
+ interface = USBH_FindInterface(phost, AC_CLASS, USB_SUBCLASS_AUDIOCONTROL, 0x00);
+
+ if(interface == 0xFF) /* Not Valid Interface */
+ {
+ USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
+ status = USBH_FAIL;
+ }
+ else
+ {
+
+
+ phost->pActiveClass->pData = (AUDIO_HandleTypeDef *)USBH_malloc (sizeof(AUDIO_HandleTypeDef));
+ AUDIO_Handle = phost->pActiveClass->pData;
+ USBH_memset(AUDIO_Handle, 0, sizeof(AUDIO_HandleTypeDef));
+
+
+ /* 1st Step: Find Audio Interfaces */
+ out_status = USBH_AUDIO_FindAudioStreamingIN (phost);
+
+ in_status = USBH_AUDIO_FindAudioStreamingOUT(phost);
+
+ if((out_status == USBH_FAIL) && (in_status == USBH_FAIL))
+ {
+ USBH_DbgLog ("%s class configuration not supported.", phost->pActiveClass->Name);
+ }
+ else
+ {
+ /* 2nd Step: Select Audio Streaming Interfaces with largest endpoint size : default behavior*/
+ for (index = 0; index < AUDIO_MAX_AUDIO_STD_INTERFACE; index ++)
+ {
+ if( AUDIO_Handle->stream_out[index].valid == 1)
+ {
+ if(ep_size_out < AUDIO_Handle->stream_out[index].EpSize)
+ {
+ ep_size_out = AUDIO_Handle->stream_out[index].EpSize;
+ AUDIO_Handle->headphone.interface = AUDIO_Handle->stream_out[index].interface;
+ AUDIO_Handle->headphone.AltSettings = AUDIO_Handle->stream_out[index].AltSettings;
+ AUDIO_Handle->headphone.Ep = AUDIO_Handle->stream_out[index].Ep;
+ AUDIO_Handle->headphone.EpSize = AUDIO_Handle->stream_out[index].EpSize;
+ AUDIO_Handle->headphone.Poll = AUDIO_Handle->stream_out[index].Poll;
+ AUDIO_Handle->headphone.supported = 1;
+ }
+ }
+
+ if( AUDIO_Handle->stream_in[index].valid == 1)
+ {
+ if(ep_size_in < AUDIO_Handle->stream_in[index].EpSize)
+ {
+ ep_size_in = AUDIO_Handle->stream_in[index].EpSize;
+ AUDIO_Handle->microphone.interface = AUDIO_Handle->stream_in[index].interface;
+ AUDIO_Handle->microphone.AltSettings = AUDIO_Handle->stream_in[index].AltSettings;
+ AUDIO_Handle->microphone.Ep = AUDIO_Handle->stream_in[index].Ep;
+ AUDIO_Handle->microphone.EpSize = AUDIO_Handle->stream_in[index].EpSize;
+ AUDIO_Handle->microphone.Poll = AUDIO_Handle->stream_out[index].Poll;
+ AUDIO_Handle->microphone.supported = 1;
+ }
+ }
+ }
+
+ if(USBH_AUDIO_FindHIDControl(phost) == USBH_OK)
+ {
+ AUDIO_Handle->control.supported = 1;
+ }
+
+ /* 3rd Step: Find and Parse Audio interfaces */
+ USBH_AUDIO_ParseCSDescriptors (phost);
+
+
+ /* 4th Step: Open the Audio streaming pipes*/
+ if(AUDIO_Handle->headphone.supported == 1)
+ {
+ USBH_AUDIO_BuildHeadphonePath (phost);
+
+ AUDIO_Handle->headphone.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->headphone.Ep);
+
+ /* Open pipe for IN endpoint */
+ USBH_OpenPipe (phost,
+ AUDIO_Handle->headphone.Pipe,
+ AUDIO_Handle->headphone.Ep,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_ISOC,
+ AUDIO_Handle->headphone.EpSize);
+
+ USBH_LL_SetToggle (phost, AUDIO_Handle->headphone.Pipe, 0);
+
+ }
+
+ if(AUDIO_Handle->microphone.supported == 1)
+ {
+ USBH_AUDIO_BuildMicrophonePath (phost);
+ AUDIO_Handle->microphone.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->microphone.Ep);
+
+ /* Open pipe for IN endpoint */
+ USBH_OpenPipe (phost,
+ AUDIO_Handle->microphone.Pipe,
+ AUDIO_Handle->microphone.Ep,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_ISOC,
+ AUDIO_Handle->microphone.EpSize);
+
+ USBH_LL_SetToggle (phost, AUDIO_Handle->microphone.Pipe, 0);
+ }
+
+ if(AUDIO_Handle->control.supported == 1)
+ {
+ AUDIO_Handle->control.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->control.Ep);
+
+ /* Open pipe for IN endpoint */
+ USBH_OpenPipe (phost,
+ AUDIO_Handle->control.Pipe,
+ AUDIO_Handle->control.Ep,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_INTR,
+ AUDIO_Handle->control.EpSize);
+
+ USBH_LL_SetToggle (phost, AUDIO_Handle->control.Pipe, 0);
+
+ }
+
+ AUDIO_Handle->req_state = AUDIO_REQ_INIT;
+ AUDIO_Handle->control_state = AUDIO_CONTROL_INIT;
+
+ status = USBH_OK;
+ }
+ }
+ return status;
+}
+
+
+
+/**
+ * @brief USBH_AUDIO_InterfaceDeInit
+ * The function DeInit the Pipes used for the Audio class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_InterfaceDeInit (USBH_HandleTypeDef *phost)
+{
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+
+ if(AUDIO_Handle->microphone.Pipe != 0x00)
+ {
+ USBH_ClosePipe (phost, AUDIO_Handle->microphone.Pipe);
+ USBH_FreePipe (phost, AUDIO_Handle->microphone.Pipe);
+ AUDIO_Handle->microphone.Pipe = 0; /* Reset the pipe as Free */
+ }
+
+ if( AUDIO_Handle->headphone.Pipe != 0x00)
+ {
+ USBH_ClosePipe(phost, AUDIO_Handle->headphone.Pipe);
+ USBH_FreePipe (phost, AUDIO_Handle->headphone.Pipe);
+ AUDIO_Handle->headphone.Pipe = 0; /* Reset the pipe as Free */
+ }
+
+ if( AUDIO_Handle->control.Pipe != 0x00)
+ {
+ USBH_ClosePipe(phost, AUDIO_Handle->control.Pipe);
+ USBH_FreePipe (phost, AUDIO_Handle->control.Pipe);
+ AUDIO_Handle->control.Pipe = 0; /* Reset the pipe as Free */
+ }
+
+ if(phost->pActiveClass->pData)
+ {
+ USBH_free (phost->pActiveClass->pData);
+ phost->pActiveClass->pData = 0;
+ }
+ return USBH_OK ;
+}
+
+/**
+ * @brief USBH_AUDIO_ClassRequest
+ * The function is responsible for handling Standard requests
+ * for Audio class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_ClassRequest(USBH_HandleTypeDef *phost)
+{
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_StatusTypeDef req_status = USBH_BUSY;
+
+ /* Switch AUDIO REQ state machine */
+ switch (AUDIO_Handle->req_state)
+ {
+ case AUDIO_REQ_INIT:
+ case AUDIO_REQ_SET_DEFAULT_IN_INTERFACE:
+ if(AUDIO_Handle->microphone.supported == 1)
+ {
+ req_status = USBH_SetInterface(phost,
+ AUDIO_Handle->microphone.interface,
+ 0);
+
+ if(req_status == USBH_OK)
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE;
+ }
+
+ }
+ else
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE:
+ if(AUDIO_Handle->headphone.supported == 1)
+ {
+ req_status = USBH_SetInterface(phost,
+ AUDIO_Handle->headphone.interface,
+ 0);
+
+ if(req_status == USBH_OK)
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_CS_REQUESTS;
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME;
+
+ AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature;
+ AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels;
+ }
+ }
+ else
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_CS_REQUESTS;
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case AUDIO_REQ_CS_REQUESTS:
+ if(USBH_AUDIO_HandleCSRequest (phost) == USBH_OK)
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_SET_IN_INTERFACE;
+ }
+ break;
+
+ case AUDIO_REQ_SET_IN_INTERFACE:
+ if(AUDIO_Handle->microphone.supported == 1)
+ {
+ req_status = USBH_SetInterface(phost,
+ AUDIO_Handle->microphone.interface,
+ AUDIO_Handle->microphone.AltSettings);
+
+ if(req_status == USBH_OK)
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_SET_OUT_INTERFACE;
+ }
+ }
+ else
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_SET_OUT_INTERFACE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+ case AUDIO_REQ_SET_OUT_INTERFACE:
+ if(AUDIO_Handle->headphone.supported == 1)
+ {
+ req_status = USBH_SetInterface(phost,
+ AUDIO_Handle->headphone.interface,
+ AUDIO_Handle->headphone.AltSettings);
+
+ if(req_status == USBH_OK)
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_IDLE;
+ }
+
+ }
+ else
+ {
+ AUDIO_Handle->req_state = AUDIO_REQ_IDLE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+ case AUDIO_REQ_IDLE:
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_INIT;
+ phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
+ status = USBH_OK;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
+#endif
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_AUDIO_CSRequest
+ * The function is responsible for handling AC Specific requests for a specific feature and channel
+ * for Audio class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_CSRequest(USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel)
+{
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_StatusTypeDef req_status = USBH_BUSY;
+
+ /* Switch AUDIO REQ state machine */
+ switch (AUDIO_Handle->cs_req_state)
+ {
+ case AUDIO_REQ_GET_VOLUME:
+ req_status = USBH_AC_GetCur(phost,
+ UAC_FEATURE_UNIT, /* subtype */
+ feature, /* feature */
+ VOLUME_CONTROL, /* Selector */
+ channel, /* channel */
+ 0x02); /* length */
+ if(req_status != USBH_BUSY)
+ {
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_MIN_VOLUME;
+ AUDIO_Handle->headphone.attribute.volume = LE16(&(AUDIO_Handle->mem[0]));
+ }
+ break;
+
+ case AUDIO_REQ_GET_MIN_VOLUME:
+ req_status = USBH_AC_GetMin(phost,
+ UAC_FEATURE_UNIT, /* subtype */
+ feature, /* feature */
+ VOLUME_CONTROL, /* Selector */
+ channel, /* channel */
+ 0x02); /* length */
+ if(req_status != USBH_BUSY)
+ {
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_MAX_VOLUME;
+ AUDIO_Handle->headphone.attribute.volumeMin = LE16(&AUDIO_Handle->mem[0]);
+ }
+ break;
+
+ case AUDIO_REQ_GET_MAX_VOLUME:
+ req_status = USBH_AC_GetMax(phost,
+ UAC_FEATURE_UNIT, /* subtype */
+ feature, /* feature */
+ VOLUME_CONTROL, /* Selector */
+ channel, /* channel */
+ 0x02); /* length */
+ if(req_status != USBH_BUSY)
+ {
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_RESOLUTION;
+ AUDIO_Handle->headphone.attribute.volumeMax = LE16(&AUDIO_Handle->mem[0]);
+
+ if (AUDIO_Handle->headphone.attribute.volumeMax < AUDIO_Handle->headphone.attribute.volumeMin)
+ {
+ AUDIO_Handle->headphone.attribute.volumeMax = 0xFF00;
+ }
+ }
+ break;
+
+ case AUDIO_REQ_GET_RESOLUTION:
+ req_status = USBH_AC_GetRes(phost,
+ UAC_FEATURE_UNIT, /* subtype */
+ feature, /* feature */
+ VOLUME_CONTROL, /* Selector */
+ channel, /* channel */
+ 0x02); /* length */
+ if(req_status != USBH_BUSY)
+ {
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_CS_IDLE;
+ AUDIO_Handle->headphone.attribute.resolution = LE16(&AUDIO_Handle->mem[0]);
+ }
+ break;
+
+
+ case AUDIO_REQ_CS_IDLE:
+ status = USBH_OK;
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_AUDIO_HandleCSRequest
+ * The function is responsible for handling AC Specific requests for a all features
+ * and associated channels for Audio class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_HandleCSRequest(USBH_HandleTypeDef *phost)
+{
+
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_StatusTypeDef cs_status = USBH_BUSY;
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+
+ cs_status = USBH_AUDIO_CSRequest(phost,
+ AUDIO_Handle->temp_feature,
+ AUDIO_Handle->temp_channels);
+
+ if(cs_status != USBH_BUSY)
+ {
+
+ if(AUDIO_Handle->temp_channels == 1)
+ {
+ AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature;
+ AUDIO_Handle->temp_channels = 0;
+ status = USBH_OK;
+ }
+ else
+ {
+ AUDIO_Handle->temp_channels--;
+ }
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_AUDIO_Process
+ * The function is for managing state machine for Audio data transfers
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_Process (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+
+ if(AUDIO_Handle->headphone.supported == 1)
+ {
+ USBH_AUDIO_OutputStream (phost);
+ }
+
+ if(AUDIO_Handle->microphone.supported == 1)
+ {
+ USBH_AUDIO_InputStream (phost);
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_AUDIO_SOFProcess
+ * The function is for managing the SOF callback
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_SOFProcess (USBH_HandleTypeDef *phost)
+{
+ return USBH_OK;
+}
+/**
+ * @brief Find IN Audio Streaming interfaces
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingIN(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface, alt_settings;
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /* Look For AUDIOSTREAMING IN interface */
+ alt_settings = 0;
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == AC_CLASS)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING))
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0))
+ {
+ AUDIO_Handle->stream_in[alt_settings].Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ AUDIO_Handle->stream_in[alt_settings].EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ AUDIO_Handle->stream_in[alt_settings].interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber;
+ AUDIO_Handle->stream_in[alt_settings].AltSettings = phost->device.CfgDesc.Itf_Desc[interface].bAlternateSetting;
+ AUDIO_Handle->stream_in[alt_settings].Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval;
+ AUDIO_Handle->stream_in[alt_settings].valid = 1;
+ alt_settings++;
+ }
+ }
+ }
+
+ if(alt_settings > 0)
+ {
+ status = USBH_OK;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Find OUT Audio Streaming interfaces
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingOUT(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface, alt_settings;
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /* Look For AUDIOSTREAMING IN interface */
+ alt_settings = 0;
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == AC_CLASS)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING))
+ {
+ if(((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) == 0x00)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0))
+ {
+ AUDIO_Handle->stream_out[alt_settings].Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ AUDIO_Handle->stream_out[alt_settings].EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ AUDIO_Handle->stream_out[alt_settings].interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber;
+ AUDIO_Handle->stream_out[alt_settings].AltSettings = phost->device.CfgDesc.Itf_Desc[interface].bAlternateSetting;
+ AUDIO_Handle->stream_out[alt_settings].Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval;
+ AUDIO_Handle->stream_out[alt_settings].valid = 1;
+ alt_settings++;
+ }
+ }
+ }
+
+ if(alt_settings > 0)
+ {
+ status = USBH_OK;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Find HID Control interfaces
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_FindHIDControl(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface;
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /* Look For AUDIOCONTROL interface */
+ interface = USBH_FindInterface(phost, AC_CLASS, USB_SUBCLASS_AUDIOCONTROL, 0xFF);
+ if(interface != 0xFF)
+ {
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == 0x03)&& /*HID*/
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0))
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) == 0x80)
+ {
+ AUDIO_Handle->control.Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ AUDIO_Handle->control.EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ AUDIO_Handle->control.interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber;
+ AUDIO_Handle->control.Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval;
+ AUDIO_Handle->control.supported = 1;
+ status = USBH_OK;
+ break;
+ }
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Parse AC and interfaces Descriptors
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_ParseCSDescriptors(USBH_HandleTypeDef *phost)
+{
+ USBH_DescHeader_t *pdesc ;
+ uint16_t ptr;
+ int8_t itf_index = 0;
+ int8_t itf_number = 0;
+ int8_t alt_setting;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+ pdesc = (USBH_DescHeader_t *)(phost->device.CfgDesc_Raw);
+ ptr = USB_LEN_CFG_DESC;
+
+ AUDIO_Handle->class_desc.FeatureUnitNum = 0;
+ AUDIO_Handle->class_desc.InputTerminalNum = 0;
+ AUDIO_Handle->class_desc.OutputTerminalNum = 0;
+ AUDIO_Handle->class_desc.ASNum = 0;
+
+ while(ptr < phost->device.CfgDesc.wTotalLength)
+ {
+ pdesc = USBH_GetNextDesc((void *)pdesc, &ptr);
+
+ switch (pdesc->bDescriptorType)
+ {
+
+ case USB_DESC_TYPE_INTERFACE:
+ itf_number = *((uint8_t *)pdesc + 2);
+ alt_setting = *((uint8_t *)pdesc + 3);
+ itf_index = USBH_FindInterfaceIndex (phost, itf_number, alt_setting);
+ break;
+
+ case USB_DESC_TYPE_CS_INTERFACE:
+ if(itf_number <= phost->device.CfgDesc.bNumInterfaces)
+ {
+
+ ParseCSDescriptors(&AUDIO_Handle->class_desc,
+ phost->device.CfgDesc.Itf_Desc[itf_index].bInterfaceSubClass,
+ (uint8_t *)pdesc);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return USBH_OK;
+}
+
+/**
+ * @brief Parse AC interfaces
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef ParseCSDescriptors(AUDIO_ClassSpecificDescTypedef *class_desc,
+ uint8_t ac_subclass,
+ uint8_t *pdesc)
+{
+ if(ac_subclass == USB_SUBCLASS_AUDIOCONTROL)
+ {
+ switch(pdesc[2])
+ {
+ case UAC_HEADER:
+ class_desc->cs_desc.HeaderDesc = (AUDIO_HeaderDescTypeDef *)pdesc;
+ break;
+
+ case UAC_INPUT_TERMINAL:
+ class_desc->cs_desc.InputTerminalDesc[class_desc->InputTerminalNum++] = (AUDIO_ITDescTypeDef*) pdesc;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ class_desc->cs_desc.OutputTerminalDesc[class_desc->OutputTerminalNum++] = (AUDIO_OTDescTypeDef*) pdesc;
+ break;
+
+ case UAC_FEATURE_UNIT:
+ class_desc->cs_desc.FeatureUnitDesc[class_desc->FeatureUnitNum++] = (AUDIO_FeatureDescTypeDef*) pdesc;
+ break;
+
+ case UAC_SELECTOR_UNIT:
+ class_desc->cs_desc.SelectorUnitDesc[class_desc->SelectorUnitNum++] = (AUDIO_SelectorDescTypeDef*) pdesc;
+ break;
+
+ case UAC_MIXER_UNIT:
+ class_desc->cs_desc.MixerUnitDesc[class_desc->MixerUnitNum++] = (AUDIO_MixerDescTypeDef*) pdesc;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if(ac_subclass == USB_SUBCLASS_AUDIOSTREAMING)
+ {
+ switch(pdesc[2])
+ {
+ case UAC_AS_GENERAL:
+ class_desc->as_desc[class_desc->ASNum].GeneralDesc = (AUDIO_ASGeneralDescTypeDef*) pdesc;
+ break;
+ case UAC_FORMAT_TYPE:
+ class_desc->as_desc[class_desc->ASNum++].FormatTypeDesc = (AUDIO_ASFormatTypeDescTypeDef*) pdesc;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return USBH_OK;
+}
+
+
+/**
+ * @brief Link a Unit to next associated one
+ * @param phost: Host handle
+ * @param UnitID: Unit identifer
+ * @retval UnitID, Index and Type of the assicated Unit
+ */
+static int32_t USBH_AUDIO_FindLinkedUnit(USBH_HandleTypeDef *phost, uint8_t UnitID)
+{
+ uint8_t Index;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /* Find Feature Unit */
+ for(Index = 0; Index < AUDIO_Handle->class_desc.FeatureUnitNum; Index ++)
+ {
+ if(AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[Index]->bSourceID == UnitID)
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[Index]->bUnitID;
+
+ return ((UnitID << 16) | (UAC_FEATURE_UNIT << 8) | Index);
+ }
+ }
+
+ /* Find Mixer Unit */
+ for(Index = 0; Index < AUDIO_Handle->class_desc.MixerUnitNum; Index ++)
+ {
+ if((AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bSourceID0 == UnitID)||
+ (AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bSourceID1 == UnitID))
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bUnitID;
+
+ return ((UnitID << 16) | (UAC_MIXER_UNIT << 8) | Index);
+ }
+ }
+
+
+ /* Find Selector Unit */
+ for(Index = 0; Index < AUDIO_Handle->class_desc.SelectorUnitNum; Index ++)
+ {
+ if(AUDIO_Handle->class_desc.cs_desc.SelectorUnitDesc[Index]->bSourceID0 == UnitID)
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.SelectorUnitDesc[Index]->bUnitID;
+
+ return ((UnitID << 16) | (UAC_SELECTOR_UNIT << 8) | Index);
+ }
+ }
+
+
+ /* Find OT Unit */
+ for(Index = 0; Index < AUDIO_Handle->class_desc.OutputTerminalNum; Index ++)
+ {
+ if(AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->bSourceID == UnitID)
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->bTerminalID;
+
+ return ((UnitID << 16) | (UAC_OUTPUT_TERMINAL << 8) | Index);
+ }
+ }
+
+ /* No associated Unit found */
+ return -1;
+}
+
+/**
+ * @brief Build full path for Microphone device
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_BuildMicrophonePath(USBH_HandleTypeDef *phost)
+{
+ uint8_t UnitID = 0, Type, Index;
+ uint32_t value;
+ uint8_t terminalIndex;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /*Find microphone IT*/
+ for(terminalIndex = 0; terminalIndex < AUDIO_Handle->class_desc.InputTerminalNum; terminalIndex++)
+ {
+ if(LE16(AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->wTerminalType) == 0x201)
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bTerminalID;
+ AUDIO_Handle->microphone.asociated_channels = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bNrChannels;
+ break;
+ }
+ }
+
+ do
+ {
+ value = USBH_AUDIO_FindLinkedUnit(phost, UnitID);
+ Index = value & 0xFF;
+ Type = (value >> 8) & 0xFF;
+ UnitID = (value >> 16) & 0xFF;
+
+ switch (Type)
+ {
+ case UAC_FEATURE_UNIT:
+ AUDIO_Handle->microphone.asociated_feature = Index;
+ break;
+
+ case UAC_MIXER_UNIT:
+ AUDIO_Handle->microphone.asociated_mixer = Index;
+ break;
+
+ case UAC_SELECTOR_UNIT:
+ AUDIO_Handle->microphone.asociated_selector = Index;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ AUDIO_Handle->microphone.asociated_terminal = Index;
+ break;
+ }
+ }
+ while ((Type != UAC_OUTPUT_TERMINAL) && (value > 0));
+
+
+
+ return USBH_OK;
+}
+
+/**
+ * @brief Build full path for Headphone device
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_BuildHeadphonePath(USBH_HandleTypeDef *phost)
+{
+ uint8_t UnitID = 0, Type, Index;
+ uint32_t value;
+ uint8_t terminalIndex;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ /*Find association betwen audio streaming and microphone*/
+ for(terminalIndex = 0; terminalIndex < AUDIO_Handle->class_desc.InputTerminalNum; terminalIndex++)
+ {
+ if(LE16(AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->wTerminalType) == 0x101)
+ {
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bTerminalID;
+ AUDIO_Handle->headphone.asociated_channels = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bNrChannels;
+ break;
+ }
+ }
+
+ for(Index = 0; Index < AUDIO_Handle->class_desc.ASNum; Index++)
+ {
+ if(AUDIO_Handle->class_desc.as_desc[Index].GeneralDesc->bTerminalLink == UnitID)
+ {
+ AUDIO_Handle->headphone.asociated_as = Index;
+ break;
+ }
+ }
+
+ do
+ {
+ value = USBH_AUDIO_FindLinkedUnit(phost, UnitID);
+ Index = value & 0xFF;
+ Type = (value >> 8) & 0xFF;
+ UnitID = (value >> 16) & 0xFF;
+
+ switch (Type)
+ {
+ case UAC_FEATURE_UNIT:
+ AUDIO_Handle->headphone.asociated_feature = Index;
+ break;
+
+ case UAC_MIXER_UNIT:
+ AUDIO_Handle->headphone.asociated_mixer = Index;
+ break;
+
+ case UAC_SELECTOR_UNIT:
+ AUDIO_Handle->headphone.asociated_selector = Index;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ AUDIO_Handle->headphone.asociated_terminal = Index;
+ if(LE16(AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->wTerminalType) != 0x103)
+ {
+ return USBH_OK;
+ }
+ break;
+ }
+ }
+ while ((Type != UAC_OUTPUT_TERMINAL) && (value > 0));
+
+ return USBH_FAIL;
+}
+
+
+/**
+ * @brief Handle Set Cur request
+ * @param phost: Host handle
+ * @param subtype: subtype index
+ * @param feature: feature index
+ * @param controlSelector: control code
+ * @param channel: channel index
+ * @param length: Command length
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AC_SetCur(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length)
+{
+ uint16_t wValue,wIndex,wLength;
+ uint8_t UnitID,InterfaceNum;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(subtype)
+ {
+ case UAC_INPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ AUDIO_Handle->mem[0] = 0x00;
+
+ wLength = 1;
+ break;
+ case UAC_FEATURE_UNIT:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ /*holds the CS(control selector ) and CN (channel number)*/
+ wValue = (controlSelector << 8) | channel;
+ wLength = length;
+ break;
+ }
+
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_SET_CUR;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength ));
+
+}
+
+/**
+ * @brief Handle Get Cur request
+ * @param phost: Host handle
+ * @param subtype: subtype index
+ * @param feature: feature index
+ * @param controlSelector: control code
+ * @param channel: channel index
+ * @param length: Command length
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AC_GetCur(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length)
+{
+ uint16_t wValue = 0, wIndex = 0,wLength = 0;
+ uint8_t UnitID = 0, InterfaceNum = 0;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(subtype)
+ {
+ case UAC_INPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ AUDIO_Handle->mem[0] = 0x00;
+
+ wLength = 1;
+ break;
+ case UAC_FEATURE_UNIT:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ /*holds the CS(control selector ) and CN (channel number)*/
+ wValue = (controlSelector << 8) | channel;
+ wLength = length;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ wLength = 1;
+ break;
+ }
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_GET_CUR;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength ));
+
+}
+
+
+/**
+ * @brief Handle Get Max request
+ * @param phost: Host handle
+ * @param subtype: subtype index
+ * @param feature: feature index
+ * @param controlSelector: control code
+ * @param channel: channel index
+ * @param length: Command length
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AC_GetMax(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length)
+{
+ uint16_t wValue = 0, wIndex = 0, wLength = 0;
+ uint8_t UnitID = 0, InterfaceNum = 0;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(subtype)
+ {
+ case UAC_INPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ AUDIO_Handle->mem[0] = 0x00;
+
+ wLength = 1;
+ break;
+ case UAC_FEATURE_UNIT:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ /*holds the CS(control selector ) and CN (channel number)*/
+ wValue = (controlSelector << 8) | channel;
+ wLength = length;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ wLength = 1;
+ break;
+ }
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_GET_MAX;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength ));
+
+}
+
+
+
+/**
+ * @brief Handle Get Res request
+ * @param phost: Host handle
+ * @param subtype: subtype index
+ * @param feature: feature index
+ * @param controlSelector: control code
+ * @param channel: channel index
+ * @param length: Command length
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AC_GetRes(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length)
+{
+ uint16_t wValue = 0, wIndex = 0, wLength = 0;
+ uint8_t UnitID = 0, InterfaceNum = 0;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(subtype)
+ {
+ case UAC_INPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ AUDIO_Handle->mem[0] = 0x00;
+
+ wLength = 1;
+ break;
+ case UAC_FEATURE_UNIT:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ /*holds the CS(control selector ) and CN (channel number)*/
+ wValue = (controlSelector << 8) | channel;
+ wLength = length;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ wLength = 1;
+ break;
+ }
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_GET_RES;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength ));
+
+}
+
+/**
+ * @brief Handle Get Min request
+ * @param phost: Host handle
+ * @param subtype: subtype index
+ * @param feature: feature index
+ * @param controlSelector: control code
+ * @param channel: channel index
+ * @param length: Command length
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AC_GetMin(USBH_HandleTypeDef *phost,
+ uint8_t subtype,
+ uint8_t feature,
+ uint8_t controlSelector,
+ uint8_t channel,
+ uint16_t length)
+{
+ uint16_t wValue = 0, wIndex = 0, wLength = 0;
+ uint8_t UnitID = 0, InterfaceNum = 0;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(subtype)
+ {
+ case UAC_INPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ AUDIO_Handle->mem[0] = 0x00;
+
+ wLength = 1;
+ break;
+ case UAC_FEATURE_UNIT:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ /*holds the CS(control selector ) and CN (channel number)*/
+ wValue = (controlSelector << 8) | channel;
+ wLength = length;
+ break;
+
+ case UAC_OUTPUT_TERMINAL:
+ UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID;
+ InterfaceNum = 0; /*Always zero Control Interface */
+ wIndex = ( UnitID << 8 ) | InterfaceNum ;
+ wValue = (COPY_PROTECT_CONTROL << 8 ) ;
+ wLength = 1;
+ break;
+ }
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_GET_MIN;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength ));
+
+}
+
+/**
+ * @brief Handle Set Endpoint Controls Request
+ * @param phost: Host handle
+ * @param Ep: Endpoint address
+ * @param buf: pointer to data
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_SetEndpointControls(USBH_HandleTypeDef *phost,
+ uint8_t Ep,
+ uint8_t *buff)
+{
+ uint16_t wValue, wIndex, wLength;
+
+
+ wValue = SAMPLING_FREQ_CONTROL << 8;
+ wIndex = Ep;
+ wLength = 3; /*length of the frequency parameter*/
+
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_ENDPOINT | \
+ USB_REQ_TYPE_CLASS;
+
+ phost->Control.setup.b.bRequest = UAC_SET_CUR;
+ phost->Control.setup.b.wValue.w = wValue;
+ phost->Control.setup.b.wIndex.w = wIndex;
+ phost->Control.setup.b.wLength.w = wLength;
+
+ return(USBH_CtlReq(phost, (uint8_t *)buff, wLength ));
+
+}
+
+/**
+ * @brief Handle Input stream process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_InputStream (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+
+ return status;
+}
+
+/**
+ * @brief Handle HID Control process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_Control (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+ uint16_t attribute = 0;
+
+
+ switch(AUDIO_Handle->control_state)
+ {
+ case AUDIO_CONTROL_INIT:
+ if((phost->Timer & 1) == 0)
+ {
+ AUDIO_Handle->control.timer = phost->Timer;
+ USBH_InterruptReceiveData(phost,
+ (uint8_t *)(AUDIO_Handle->mem),
+ AUDIO_Handle->control.EpSize,
+ AUDIO_Handle->control.Pipe);
+
+ AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature;
+ AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels;
+
+ AUDIO_Handle->control_state = AUDIO_CONTROL_CHANGE ;
+ }
+ break;
+ case AUDIO_CONTROL_CHANGE:
+ if(USBH_LL_GetURBState(phost , AUDIO_Handle->control.Pipe) == USBH_URB_DONE)
+ {
+ attribute = LE16(&AUDIO_Handle->mem[0]);
+ if(USBH_AUDIO_SetControlAttribute (phost, attribute) == USBH_BUSY)
+ {
+ break;
+ }
+ }
+
+ if(( phost->Timer - AUDIO_Handle->control.timer) >= AUDIO_Handle->control.Poll)
+ {
+ AUDIO_Handle->control.timer = phost->Timer;
+
+ USBH_InterruptReceiveData(phost,
+ (uint8_t *)(AUDIO_Handle->mem),
+ AUDIO_Handle->control.EpSize,
+ AUDIO_Handle->control.Pipe);
+
+ }
+ break;
+
+ case AUDIO_CONTROL_VOLUME_UP:
+ if( USBH_AUDIO_SetControlAttribute (phost, 1) == USBH_OK)
+ {
+ AUDIO_Handle->control_state = AUDIO_CONTROL_INIT;
+ status = USBH_OK;
+ }
+ break;
+
+ case AUDIO_CONTROL_VOLUME_DOWN:
+ if( USBH_AUDIO_SetControlAttribute (phost, 2) == USBH_OK)
+ {
+ AUDIO_Handle->control_state = AUDIO_CONTROL_INIT;
+ status = USBH_OK;
+ }
+ break;
+
+ case AUDIO_CONTROL_IDLE:
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handle Output stream process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_OutputStream (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+ uint8_t *buff;
+
+
+ switch(AUDIO_Handle->play_state)
+ {
+ case AUDIO_PLAYBACK_INIT:
+
+ if( AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bSamFreqType == 0)
+ {
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP_FREQ;
+ }
+ else
+ {
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP;
+ }
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ break;
+
+ case AUDIO_PLAYBACK_SET_EP_FREQ:
+
+ buff = (uint8_t*)AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[0];
+
+ status = USBH_AUDIO_SetEndpointControls(phost, AUDIO_Handle->headphone.Ep, buff);
+ if(status == USBH_OK)
+ {
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE;
+ }
+ break;
+
+ case AUDIO_PLAYBACK_SET_EP:
+ buff = (uint8_t *)&AUDIO_Handle->headphone.frequency;
+ status = USBH_AUDIO_SetEndpointControls(phost,AUDIO_Handle->headphone.Ep, buff);
+ if(status == USBH_OK)
+ {
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE;
+ USBH_AUDIO_FrequencySet(phost);
+ }
+ break;
+ case AUDIO_PLAYBACK_IDLE:
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
+#endif
+ status = USBH_OK;
+ break;
+
+ case AUDIO_PLAYBACK_PLAY:
+ USBH_AUDIO_Transmit(phost);
+ status = USBH_OK;
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handle Transmission process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_Transmit (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch(AUDIO_Handle->processing_state)
+ {
+ case AUDIO_DATA_START_OUT:
+ /* Sync with start of Even Frame */
+ if((phost->Timer & 1) == 0)
+ {
+ AUDIO_Handle->headphone.timer = phost->Timer;
+ AUDIO_Handle->processing_state = AUDIO_DATA_OUT;
+ USBH_IsocSendData(phost,
+ AUDIO_Handle->headphone.buf,
+ AUDIO_Handle->headphone.frame_length,
+ AUDIO_Handle->headphone.Pipe);
+
+ AUDIO_Handle->headphone.partial_ptr = AUDIO_Handle->headphone.frame_length;
+ AUDIO_Handle->headphone.global_ptr = AUDIO_Handle->headphone.frame_length;
+ AUDIO_Handle->headphone.cbuf = AUDIO_Handle->headphone.buf;
+
+ }
+ break;
+
+ case AUDIO_DATA_OUT:
+ if((USBH_LL_GetURBState(phost , AUDIO_Handle->headphone.Pipe) == USBH_URB_DONE)&&
+ (( phost->Timer - AUDIO_Handle->headphone.timer) >= AUDIO_Handle->headphone.Poll))
+ {
+ AUDIO_Handle->headphone.timer = phost->Timer;
+
+ if(AUDIO_Handle->control.supported == 1)
+ {
+ USBH_AUDIO_Control (phost);
+ }
+
+ if(AUDIO_Handle->headphone.global_ptr <= AUDIO_Handle->headphone.total_length)
+ {
+ USBH_IsocSendData(phost,
+ AUDIO_Handle->headphone.cbuf,
+ AUDIO_Handle->headphone.frame_length,
+ AUDIO_Handle->headphone.Pipe);
+
+ AUDIO_Handle->headphone.cbuf += AUDIO_Handle->headphone.frame_length;
+ AUDIO_Handle->headphone.partial_ptr += AUDIO_Handle->headphone.frame_length;
+ AUDIO_Handle->headphone.global_ptr += AUDIO_Handle->headphone.frame_length;
+ }
+ else
+ {
+ AUDIO_Handle->headphone.partial_ptr = 0xFFFFFFFF;
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE;
+ }
+ }
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_AUDIO_SetFrequency
+ * Set Audio sampling parameters
+ * @param phost: Host handle
+ * @param SampleRate: Sample Rate
+ * @param NbrChannels: Number of Channels
+ * @param BitPerSample: Bit Per Sample
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_SetFrequency (USBH_HandleTypeDef *phost,
+ uint16_t SampleRate,
+ uint8_t NbrChannels,
+ uint8_t BitPerSample)
+{
+ USBH_StatusTypeDef Status = USBH_BUSY;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+ uint8_t index;
+ uint8_t change_freq = FALSE;
+ uint32_t freq_min, freq_max;
+ uint8_t num_supported_freq;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE)
+ {
+
+ if(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bSamFreqType == 0)
+ {
+ freq_min = LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[0]);
+ freq_max = LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[1]);
+
+ if(( SampleRate >= freq_min)&& (SampleRate <= freq_max))
+ {
+ change_freq = TRUE;
+ }
+ }
+ else
+ {
+
+ num_supported_freq = (AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bLength - 8)/3;
+
+
+ for(index = 0; index < num_supported_freq; index++)
+ {
+ if(SampleRate == LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[index]))
+ {
+ change_freq = TRUE;
+ break;
+ }
+ }
+ }
+
+ if(change_freq == TRUE)
+ {
+ AUDIO_Handle->headphone.frequency = SampleRate;
+ AUDIO_Handle->headphone.frame_length = (SampleRate * BitPerSample * NbrChannels) / 8000;
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP;
+ Status = USBH_OK;
+
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ * @brief USBH_AUDIO_Play
+ * Start playback process
+ * @param phost: Host handle
+ * @param buf: pointer to raw audio data
+ * @param length: total length of the audio data
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_Play (USBH_HandleTypeDef *phost, uint8_t *buf, uint32_t length)
+{
+ USBH_StatusTypeDef Status = USBH_FAIL;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE)
+ {
+ AUDIO_Handle->headphone.buf = buf;
+ AUDIO_Handle->headphone.total_length = length;
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_PLAY;
+ AUDIO_Handle->control_state = AUDIO_CONTROL_INIT;
+ AUDIO_Handle->processing_state = AUDIO_DATA_START_OUT;
+ Status = USBH_OK;
+ }
+ }
+ return Status;
+}
+
+/**
+ * @brief USBH_AUDIO_Pause
+ * Stop the playback process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_Stop (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef Status = USBH_FAIL;
+ Status = USBH_AUDIO_Suspend(phost);
+ return Status;
+}
+
+/**
+ * @brief USBH_AUDIO_Suspend
+ * Suspend the playback process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_Suspend (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef Status = USBH_FAIL;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY)
+ {
+ AUDIO_Handle->control_state = AUDIO_CONTROL_IDLE;
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE;
+ Status = USBH_OK;
+ }
+ }
+ return Status;
+}
+/**
+ * @brief USBH_AUDIO_Resume
+ * Resume the playback process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_Resume (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef Status = USBH_FAIL;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE)
+ {
+ AUDIO_Handle->control_state = AUDIO_CONTROL_INIT;
+ AUDIO_Handle->play_state = AUDIO_PLAYBACK_PLAY;
+ }
+ }
+ return Status;
+}
+/**
+ * @brief USBH_AUDIO_GetOutOffset
+ * return the current buffer pointer for OUT proces
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+int32_t USBH_AUDIO_GetOutOffset (USBH_HandleTypeDef *phost)
+{
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY)
+ {
+ return AUDIO_Handle->headphone.partial_ptr;
+ }
+ }
+ return -1;
+}
+
+/**
+ * @brief USBH_AUDIO_ChangeOutBuffer
+ * Change audio data buffer address
+ * @param phost: Host handle
+ * @param buf: buffer address
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_ChangeOutBuffer (USBH_HandleTypeDef *phost, uint8_t *buf)
+{
+ USBH_StatusTypeDef Status = USBH_FAIL;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY)
+ {
+ if(AUDIO_Handle->headphone.buf <= buf)
+ {
+ AUDIO_Handle->headphone.cbuf = buf;
+ if ( AUDIO_Handle->headphone.buf == buf)
+ {
+ AUDIO_Handle->headphone.partial_ptr = 0;
+ }
+ Status = USBH_OK;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ * @brief USBH_AUDIO_SetControlAttribute
+ * Set Control Attribute
+ * @param phost: Host handle
+ * @param attrib: control attribute
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_AUDIO_SetControlAttribute (USBH_HandleTypeDef *phost, uint8_t attrib)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ switch (attrib)
+ {
+ case 0x01:
+ AUDIO_Handle->headphone.attribute.volume += AUDIO_Handle->headphone.attribute.resolution;
+ break;
+
+ case 0x02:
+ AUDIO_Handle->headphone.attribute.volume -= AUDIO_Handle->headphone.attribute.resolution;
+ break;
+
+ }
+
+ if(AUDIO_Handle->headphone.attribute.volume > AUDIO_Handle->headphone.attribute.volumeMax)
+ {
+ AUDIO_Handle->headphone.attribute.volume =AUDIO_Handle->headphone.attribute.volumeMax;
+ }
+
+ if(AUDIO_Handle->headphone.attribute.volume < AUDIO_Handle->headphone.attribute.volumeMin)
+ {
+ AUDIO_Handle->headphone.attribute.volume =AUDIO_Handle->headphone.attribute.volumeMin;
+ }
+
+ if(AUDIO_SetVolume (phost,
+ AUDIO_Handle->temp_feature,
+ AUDIO_Handle->temp_channels,
+ AUDIO_Handle->headphone.attribute.volume) != USBH_BUSY)
+ {
+
+ if(AUDIO_Handle->temp_channels == 1)
+ {
+ AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature;
+ AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels;
+ status = USBH_OK;
+ }
+ else
+ {
+ AUDIO_Handle->temp_channels--;
+ }
+ AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME;
+ }
+
+
+ return status;
+}
+
+
+/**
+ * @brief USBH_AUDIO_SetVolume
+ * Set Volume
+ * @param phost: Host handle
+ * @param volume: VOLUME_UP/ VOLUME_DOWN
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_AUDIO_SetVolume (USBH_HandleTypeDef *phost, AUDIO_VolumeCtrlTypeDef volume_ctl)
+{
+ AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData;
+
+ if((volume_ctl == VOLUME_UP) || (volume_ctl == VOLUME_DOWN))
+ {
+ if(phost->gState == HOST_CLASS)
+ {
+ AUDIO_Handle = phost->pActiveClass->pData;
+ if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY)
+ {
+ AUDIO_Handle->control_state = (volume_ctl == VOLUME_UP)? AUDIO_CONTROL_VOLUME_UP : AUDIO_CONTROL_VOLUME_DOWN;
+ return USBH_OK;
+ }
+ }
+ }
+ return USBH_FAIL;
+}
+/**
+ * @brief AUDIO_SetVolume
+ * Set Volume
+ * @param phost: Host handle
+ * @param feature: feature Unit index
+ * @param channel: channel index
+ * @param volume: new volume
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef AUDIO_SetVolume (USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel, uint16_t volume)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ AUDIO_HandleTypeDef *AUDIO_Handle;
+
+
+ AUDIO_Handle = phost->pActiveClass->pData;
+
+ AUDIO_Handle->mem[0] = volume;
+
+ status = USBH_AC_SetCur(phost,
+ UAC_FEATURE_UNIT,
+ feature,
+ VOLUME_CONTROL,
+ channel,
+ 2);
+
+ return status;
+}
+
+/**
+ * @brief The function informs user that Settings have been changed
+ * @param pdev: Selected device
+ * @retval None
+ */
+__weak void USBH_AUDIO_FrequencySet(USBH_HandleTypeDef *phost)
+{
+
+}
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/CDC/Inc/usbh_cdc.h b/stmhal/usbhost/Class/CDC/Inc/usbh_cdc.h new file mode 100644 index 000000000..df11bfdda --- /dev/null +++ b/stmhal/usbhost/Class/CDC/Inc/usbh_cdc.h @@ -0,0 +1,449 @@ +/**
+ ******************************************************************************
+ * @file usbh_cdc.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_cdc.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_CDC_CORE_H
+#define __USBH_CDC_CORE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_CDC_CLASS
+* @{
+*/
+
+/** @defgroup USBH_CDC_CORE
+* @brief This file is the Header file for USBH_CDC_CORE.c
+* @{
+*/
+
+
+
+
+/*Communication Class codes*/
+#define USB_CDC_CLASS 0x02
+#define COMMUNICATION_INTERFACE_CLASS_CODE 0x02
+
+/*Data Interface Class Codes*/
+#define DATA_INTERFACE_CLASS_CODE 0x0A
+
+/*Communcation sub class codes*/
+#define RESERVED 0x00
+#define DIRECT_LINE_CONTROL_MODEL 0x01
+#define ABSTRACT_CONTROL_MODEL 0x02
+#define TELEPHONE_CONTROL_MODEL 0x03
+#define MULTICHANNEL_CONTROL_MODEL 0x04
+#define CAPI_CONTROL_MODEL 0x05
+#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06
+#define ATM_NETWORKING_CONTROL_MODEL 0x07
+
+
+/*Communication Interface Class Control Protocol Codes*/
+#define NO_CLASS_SPECIFIC_PROTOCOL_CODE 0x00
+#define COMMON_AT_COMMAND 0x01
+#define VENDOR_SPECIFIC 0xFF
+
+
+#define CS_INTERFACE 0x24
+#define CDC_PAGE_SIZE_64 0x40
+
+/*Class-Specific Request Codes*/
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define CDC_SET_COMM_FEATURE 0x02
+#define CDC_GET_COMM_FEATURE 0x03
+#define CDC_CLEAR_COMM_FEATURE 0x04
+
+#define CDC_SET_AUX_LINE_STATE 0x10
+#define CDC_SET_HOOK_STATE 0x11
+#define CDC_PULSE_SETUP 0x12
+#define CDC_SEND_PULSE 0x13
+#define CDC_SET_PULSE_TIME 0x14
+#define CDC_RING_AUX_JACK 0x15
+
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+#define CDC_SEND_BREAK 0x23
+
+#define CDC_SET_RINGER_PARMS 0x30
+#define CDC_GET_RINGER_PARMS 0x31
+#define CDC_SET_OPERATION_PARMS 0x32
+#define CDC_GET_OPERATION_PARMS 0x33
+#define CDC_SET_LINE_PARMS 0x34
+#define CDC_GET_LINE_PARMS 0x35
+#define CDC_DIAL_DIGITS 0x36
+#define CDC_SET_UNIT_PARAMETER 0x37
+#define CDC_GET_UNIT_PARAMETER 0x38
+#define CDC_CLEAR_UNIT_PARAMETER 0x39
+#define CDC_GET_PROFILE 0x3A
+
+#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41
+#define CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42
+#define CDC_SET_ETHERNET_PACKET_FILTER 0x43
+#define CDC_GET_ETHERNET_STATISTIC 0x44
+
+#define CDC_SET_ATM_DATA_FORMAT 0x50
+#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
+#define CDC_SET_ATM_DEFAULT_VC 0x52
+#define CDC_GET_ATM_VC_STATISTICS 0x53
+
+
+/* wValue for SetControlLineState*/
+#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002
+#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000
+#define CDC_ACTIVATE_SIGNAL_DTR 0x0001
+#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000
+
+#define LINE_CODING_STRUCTURE_SIZE 0x07
+/**
+ * @}
+ */
+
+/** @defgroup USBH_CDC_CORE_Exported_Types
+* @{
+*/
+
+/* States for CDC State Machine */
+typedef enum
+{
+ CDC_IDLE= 0,
+ CDC_SEND_DATA,
+ CDC_SEND_DATA_WAIT,
+ CDC_RECEIVE_DATA,
+ CDC_RECEIVE_DATA_WAIT,
+}
+CDC_DataStateTypeDef;
+
+typedef enum
+{
+ CDC_IDLE_STATE= 0,
+ CDC_SET_LINE_CODING_STATE,
+ CDC_GET_LAST_LINE_CODING_STATE,
+ CDC_TRANSFER_DATA,
+ CDC_ERROR_STATE,
+}
+CDC_StateTypeDef;
+
+
+/*Line coding structure*/
+typedef union _CDC_LineCodingStructure
+{
+ uint8_t Array[LINE_CODING_STRUCTURE_SIZE];
+
+ struct
+ {
+
+ uint32_t dwDTERate; /*Data terminal rate, in bits per second*/
+ uint8_t bCharFormat; /*Stop bits
+ 0 - 1 Stop bit
+ 1 - 1.5 Stop bits
+ 2 - 2 Stop bits*/
+ uint8_t bParityType; /* Parity
+ 0 - None
+ 1 - Odd
+ 2 - Even
+ 3 - Mark
+ 4 - Space*/
+ uint8_t bDataBits; /* Data bits (5, 6, 7, 8 or 16). */
+ }b;
+}
+CDC_LineCodingTypeDef;
+
+
+
+/* Header Functional Descriptor
+--------------------------------------------------------------------------------
+Offset| field | Size | Value | Description
+------|---------------------|-------|------------|------------------------------
+0 | bFunctionLength | 1 | number | Size of this descriptor.
+1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
+2 | bDescriptorSubtype | 1 | Constant | Identifier (ID) of functional
+ | | | | descriptor.
+3 | bcdCDC | 2 | |
+ | | | Number | USB Class Definitions for
+ | | | | Communication Devices Specification
+ | | | | release number in binary-coded
+ | | | | decimal
+------|---------------------|-------|------------|------------------------------
+*/
+typedef struct _FunctionalDescriptorHeader
+{
+ uint8_t bLength; /*Size of this descriptor.*/
+ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
+ uint8_t bDescriptorSubType; /* Header functional descriptor subtype as*/
+ uint16_t bcdCDC; /* USB Class Definitions for Communication
+ Devices Specification release number in
+ binary-coded decimal. */
+}
+CDC_HeaderFuncDesc_TypeDef;
+/* Call Management Functional Descriptor
+--------------------------------------------------------------------------------
+Offset| field | Size | Value | Description
+------|---------------------|-------|------------|------------------------------
+0 | bFunctionLength | 1 | number | Size of this descriptor.
+1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
+2 | bDescriptorSubtype | 1 | Constant | Call Management functional
+ | | | | descriptor subtype.
+3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration
+ | | | | supports:
+ | | | | D7..D2: RESERVED (Reset to zero)
+ | | | | D1: 0 - Device sends/receives call
+ | | | | management information only over
+ | | | | the Communication Class
+ | | | | interface.
+ | | | | 1 - Device can send/receive call
+ | \ | | management information over a
+ | | | | Data Class interface.
+ | | | | D0: 0 - Device does not handle call
+ | | | | management itself.
+ | | | | 1 - Device handles call
+ | | | | management itself.
+ | | | | The previous bits, in combination, identify
+ | | | | which call management scenario is used. If bit
+ | | | | D0 is reset to 0, then the value of bit D1 is
+ | | | | ignored. In this case, bit D1 is reset to zero for
+ | | | | future compatibility.
+4 | bDataInterface | 1 | Number | Interface number of Data Class interface
+ | | | | optionally used for call management.
+------|---------------------|-------|------------|------------------------------
+*/
+typedef struct _CallMgmtFunctionalDescriptor
+{
+ uint8_t bLength; /*Size of this functional descriptor, in bytes.*/
+ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
+ uint8_t bDescriptorSubType; /* Call Management functional descriptor subtype*/
+ uint8_t bmCapabilities; /* bmCapabilities: D0+D1 */
+ uint8_t bDataInterface; /*bDataInterface: 1*/
+}
+CDC_CallMgmtFuncDesc_TypeDef;
+/* Abstract Control Management Functional Descriptor
+--------------------------------------------------------------------------------
+Offset| field | Size | Value | Description
+------|---------------------|-------|------------|------------------------------
+0 | bFunctionLength | 1 | number | Size of functional descriptor, in bytes.
+1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
+2 | bDescriptorSubtype | 1 | Constant | Abstract Control Management
+ | | | | functional descriptor subtype.
+3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration
+ | | | | supports ((A bit value of zero means that the
+ | | | | request is not supported.) )
+ D7..D4: RESERVED (Reset to zero)
+ | | | | D3: 1 - Device supports the notification
+ | | | | Network_Connection.
+ | | | | D2: 1 - Device supports the request
+ | | | | Send_Break
+ | | | | D1: 1 - Device supports the request
+ | \ | | combination of Set_Line_Coding,
+ | | | | Set_Control_Line_State, Get_Line_Coding, and the
+ notification Serial_State.
+ | | | | D0: 1 - Device supports the request
+ | | | | combination of Set_Comm_Feature,
+ | | | | Clear_Comm_Feature, and Get_Comm_Feature.
+ | | | | The previous bits, in combination, identify
+ | | | | which requests/notifications are supported by
+ | | | | a Communication Class interface with the
+ | | | | SubClass code of Abstract Control Model.
+------|---------------------|-------|------------|------------------------------
+*/
+typedef struct _AbstractCntrlMgmtFunctionalDescriptor
+{
+ uint8_t bLength; /*Size of this functional descriptor, in bytes.*/
+ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
+ uint8_t bDescriptorSubType; /* Abstract Control Management functional
+ descriptor subtype*/
+ uint8_t bmCapabilities; /* The capabilities that this configuration supports */
+}
+CDC_AbstCntrlMgmtFuncDesc_TypeDef;
+/* Union Functional Descriptor
+--------------------------------------------------------------------------------
+Offset| field | Size | Value | Description
+------|---------------------|-------|------------|------------------------------
+0 | bFunctionLength | 1 | number | Size of this descriptor.
+1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
+2 | bDescriptorSubtype | 1 | Constant | Union functional
+ | | | | descriptor subtype.
+3 | bMasterInterface | 1 | Constant | The interface number of the
+ | | | | Communication or Data Class interface
+4 | bSlaveInterface0 | 1 | Number | nterface number of first slave or associated
+ | | | | interface in the union.
+------|---------------------|-------|------------|------------------------------
+*/
+typedef struct _UnionFunctionalDescriptor
+{
+ uint8_t bLength; /*Size of this functional descriptor, in bytes*/
+ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
+ uint8_t bDescriptorSubType; /* Union functional descriptor SubType*/
+ uint8_t bMasterInterface; /* The interface number of the Communication or
+ Data Class interface,*/
+ uint8_t bSlaveInterface0; /*Interface number of first slave*/
+}
+CDC_UnionFuncDesc_TypeDef;
+
+typedef struct _USBH_CDCInterfaceDesc
+{
+ CDC_HeaderFuncDesc_TypeDef CDC_HeaderFuncDesc;
+ CDC_CallMgmtFuncDesc_TypeDef CDC_CallMgmtFuncDesc;
+ CDC_AbstCntrlMgmtFuncDesc_TypeDef CDC_AbstCntrlMgmtFuncDesc;
+ CDC_UnionFuncDesc_TypeDef CDC_UnionFuncDesc;
+}
+CDC_InterfaceDesc_Typedef;
+
+
+/* Structure for CDC process */
+typedef struct
+{
+ uint8_t NotifPipe;
+ uint8_t NotifEp;
+ uint8_t buff[8];
+ uint16_t NotifEpSize;
+}
+CDC_CommItfTypedef ;
+
+typedef struct
+{
+ uint8_t InPipe;
+ uint8_t OutPipe;
+ uint8_t OutEp;
+ uint8_t InEp;
+ uint8_t buff[8];
+ uint16_t OutEpSize;
+ uint16_t InEpSize;
+}
+CDC_DataItfTypedef ;
+
+/* Structure for CDC process */
+typedef struct _CDC_Process
+{
+ CDC_CommItfTypedef CommItf;
+ CDC_DataItfTypedef DataItf;
+ uint8_t *pTxData;
+ uint8_t *pRxData;
+ uint32_t TxDataLength;
+ uint32_t RxDataLength;
+ CDC_InterfaceDesc_Typedef CDC_Desc;
+ CDC_LineCodingTypeDef LineCoding;
+ CDC_LineCodingTypeDef *pUserLineCoding;
+ CDC_StateTypeDef state;
+ CDC_DataStateTypeDef data_tx_state;
+ CDC_DataStateTypeDef data_rx_state;
+ uint8_t Rx_Poll;
+}
+CDC_HandleTypeDef;
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_CDC_CORE_Exported_Defines
+* @{
+*/
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_CDC_CORE_Exported_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_CDC_CORE_Exported_Variables
+* @{
+*/
+extern USBH_ClassTypeDef CDC_Class;
+#define USBH_CDC_CLASS &CDC_Class
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_CDC_CORE_Exported_FunctionsPrototype
+* @{
+*/
+
+USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost,
+ CDC_LineCodingTypeDef *linecoding);
+
+USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost,
+ CDC_LineCodingTypeDef *linecoding);
+
+USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost,
+ uint8_t *pbuff,
+ uint32_t length);
+
+USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost,
+ uint8_t *pbuff,
+ uint32_t length);
+
+
+uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost);
+
+USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost);
+
+void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost);
+
+void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost);
+
+void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost);
+
+/**
+* @}
+*/
+
+
+#endif /* __USBH_CDC_CORE_H */
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/CDC/Src/usbh_cdc.c b/stmhal/usbhost/Class/CDC/Src/usbh_cdc.c new file mode 100644 index 000000000..250e1fc7b --- /dev/null +++ b/stmhal/usbhost/Class/CDC/Src/usbh_cdc.c @@ -0,0 +1,755 @@ +/**
+ ******************************************************************************
+ * @file usbh_cdc.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the CDC Layer Handlers for USB Host CDC class.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * CDC Class Description
+ * ===================================================================
+ * This module manages the MSC class V1.11 following the "Device Class Definition
+ * for Human Interface Devices (CDC) Version 1.11 Jun 27, 2001".
+ * This driver implements the following aspects of the specification:
+ * - The Boot Interface Subclass
+ * - The Mouse and Keyboard protocols
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_cdc.h"
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_CDC_CLASS
+* @{
+*/
+
+/** @defgroup USBH_CDC_CORE
+* @brief This file includes CDC Layer Handlers for USB Host CDC class.
+* @{
+*/
+
+/** @defgroup USBH_CDC_CORE_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CDC_CORE_Private_Defines
+* @{
+*/
+#define USBH_CDC_BUFFER_SIZE 1024
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CDC_CORE_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CDC_CORE_Private_Variables
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CDC_CORE_Private_FunctionPrototypes
+* @{
+*/
+
+static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_CDC_Process(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_CDC_SOFProcess(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost,
+ CDC_LineCodingTypeDef *linecoding);
+
+static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost,
+ CDC_LineCodingTypeDef *linecoding);
+
+static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost);
+
+static void CDC_ProcessReception(USBH_HandleTypeDef *phost);
+
+USBH_ClassTypeDef CDC_Class =
+{
+ "CDC",
+ USB_CDC_CLASS,
+ USBH_CDC_InterfaceInit,
+ USBH_CDC_InterfaceDeInit,
+ USBH_CDC_ClassRequest,
+ USBH_CDC_Process,
+ USBH_CDC_SOFProcess,
+ NULL,
+};
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CDC_CORE_Private_Functions
+* @{
+*/
+
+/**
+ * @brief USBH_CDC_InterfaceInit
+ * The function init the CDC class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost)
+{
+
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ uint8_t interface;
+ CDC_HandleTypeDef *CDC_Handle;
+
+ interface = USBH_FindInterface(phost,
+ COMMUNICATION_INTERFACE_CLASS_CODE,
+ ABSTRACT_CONTROL_MODEL,
+ COMMON_AT_COMMAND);
+
+ if(interface == 0xFF) /* No Valid Interface */
+ {
+ USBH_DbgLog ("Cannot Find the interface for Communication Interface Class.", phost->pActiveClass->Name);
+ }
+ else
+ {
+ USBH_SelectInterface (phost, interface);
+ phost->pActiveClass->pData = (CDC_HandleTypeDef *)USBH_malloc (sizeof(CDC_HandleTypeDef));
+ CDC_Handle = phost->pActiveClass->pData;
+
+ /*Collect the notification endpoint address and length*/
+ if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80)
+ {
+ CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ }
+
+ /*Allocate the length for host channel number in*/
+ CDC_Handle->CommItf.NotifPipe = USBH_AllocPipe(phost, CDC_Handle->CommItf.NotifEp);
+
+ /* Open pipe for Notification endpoint */
+ USBH_OpenPipe (phost,
+ CDC_Handle->CommItf.NotifPipe,
+ CDC_Handle->CommItf.NotifEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_INTR,
+ CDC_Handle->CommItf.NotifEpSize);
+
+ USBH_LL_SetToggle (phost, CDC_Handle->CommItf.NotifPipe, 0);
+
+ interface = USBH_FindInterface(phost,
+ DATA_INTERFACE_CLASS_CODE,
+ RESERVED,
+ NO_CLASS_SPECIFIC_PROTOCOL_CODE);
+
+ if(interface == 0xFF) /* No Valid Interface */
+ {
+ USBH_DbgLog ("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name);
+ }
+ else
+ {
+ /*Collect the class specific endpoint address and length*/
+ if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80)
+ {
+ CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ }
+ else
+ {
+ CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
+ CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
+ }
+
+ if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80)
+ {
+ CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress;
+ CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize;
+ }
+ else
+ {
+ CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress;
+ CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize;
+ }
+
+ /*Allocate the length for host channel number out*/
+ CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp);
+
+ /*Allocate the length for host channel number in*/
+ CDC_Handle->DataItf.InPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.InEp);
+
+ /* Open channel for OUT endpoint */
+ USBH_OpenPipe (phost,
+ CDC_Handle->DataItf.OutPipe,
+ CDC_Handle->DataItf.OutEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_BULK,
+ CDC_Handle->DataItf.OutEpSize);
+ /* Open channel for IN endpoint */
+ USBH_OpenPipe (phost,
+ CDC_Handle->DataItf.InPipe,
+ CDC_Handle->DataItf.InEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_BULK,
+ CDC_Handle->DataItf.InEpSize);
+
+ CDC_Handle->state = CDC_IDLE_STATE;
+
+ USBH_LL_SetToggle (phost, CDC_Handle->DataItf.OutPipe,0);
+ USBH_LL_SetToggle (phost, CDC_Handle->DataItf.InPipe,0);
+ status = USBH_OK;
+ }
+ }
+ return status;
+}
+
+
+
+/**
+ * @brief USBH_CDC_InterfaceDeInit
+ * The function DeInit the Pipes used for the CDC class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if ( CDC_Handle->CommItf.NotifPipe)
+ {
+ USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe);
+ USBH_FreePipe (phost, CDC_Handle->CommItf.NotifPipe);
+ CDC_Handle->CommItf.NotifPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if ( CDC_Handle->DataItf.InPipe)
+ {
+ USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe);
+ USBH_FreePipe (phost, CDC_Handle->DataItf.InPipe);
+ CDC_Handle->DataItf.InPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if ( CDC_Handle->DataItf.OutPipe)
+ {
+ USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe);
+ USBH_FreePipe (phost, CDC_Handle->DataItf.OutPipe);
+ CDC_Handle->DataItf.OutPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if(phost->pActiveClass->pData)
+ {
+ USBH_free (phost->pActiveClass->pData);
+ phost->pActiveClass->pData = 0;
+ }
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_CDC_ClassRequest
+ * The function is responsible for handling Standard requests
+ * for CDC class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ /*Issue the get line coding request*/
+ status = GetLineCoding(phost, &CDC_Handle->LineCoding);
+ if(status == USBH_OK)
+ {
+ phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
+ }
+ return status;
+}
+
+
+/**
+ * @brief USBH_CDC_Process
+ * The function is for managing state machine for CDC data transfers
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_StatusTypeDef req_status = USBH_OK;
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ switch(CDC_Handle->state)
+ {
+
+ case CDC_IDLE_STATE:
+ status = USBH_OK;
+ break;
+
+ case CDC_SET_LINE_CODING_STATE:
+ req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding);
+
+ if(req_status == USBH_OK)
+ {
+ CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE;
+ }
+
+ else if(req_status != USBH_BUSY)
+ {
+ CDC_Handle->state = CDC_ERROR_STATE;
+ }
+ break;
+
+
+ case CDC_GET_LAST_LINE_CODING_STATE:
+ req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding));
+
+ if(req_status == USBH_OK)
+ {
+ CDC_Handle->state = CDC_IDLE_STATE;
+
+ if((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) &&
+ (CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) &&
+ (CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) &&
+ (CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate))
+ {
+ USBH_CDC_LineCodingChanged(phost);
+ }
+ }
+
+ else if(req_status != USBH_BUSY)
+ {
+ CDC_Handle->state = CDC_ERROR_STATE;
+ }
+
+ break;
+
+ case CDC_TRANSFER_DATA:
+ CDC_ProcessTransmission(phost);
+ CDC_ProcessReception(phost);
+ break;
+
+ case CDC_ERROR_STATE:
+ req_status = USBH_ClrFeature(phost, 0x00);
+
+ if(req_status == USBH_OK )
+ {
+ /*Change the state to waiting*/
+ CDC_Handle->state = CDC_IDLE_STATE ;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_CDC_SOFProcess
+ * The function is for managing SOF callback
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_CDC_SOFProcess (USBH_HandleTypeDef *phost)
+{
+ return USBH_OK;
+}
+
+
+ /**
+ * @brief USBH_CDC_Stop
+ * Stop current CDC Transmission
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ CDC_Handle->state = CDC_IDLE_STATE;
+
+ USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe);
+ USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe);
+ USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe);
+ }
+ return USBH_OK;
+}
+/**
+ * @brief This request allows the host to find out the currently
+ * configured line coding.
+ * @param pdev: Selected device
+ * @retval USBH_StatusTypeDef : USB ctl xfer status
+ */
+static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding)
+{
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
+ USB_REQ_RECIPIENT_INTERFACE;
+
+ phost->Control.setup.b.bRequest = CDC_GET_LINE_CODING;
+ phost->Control.setup.b.wValue.w = 0;
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE;
+
+ return USBH_CtlReq(phost, linecoding->Array, LINE_CODING_STRUCTURE_SIZE);
+}
+
+
+/**
+ * @brief This request allows the host to specify typical asynchronous
+ * line-character formatting properties
+ * This request applies to asynchronous byte stream data class interfaces
+ * and endpoints
+ * @param pdev: Selected device
+ * @retval USBH_StatusTypeDef : USB ctl xfer status
+ */
+static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin)
+{
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
+ USB_REQ_RECIPIENT_INTERFACE;
+
+ phost->Control.setup.b.bRequest = CDC_SET_LINE_CODING;
+ phost->Control.setup.b.wValue.w = 0;
+
+ phost->Control.setup.b.wIndex.w = 0;
+
+ phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE;
+
+ return USBH_CtlReq(phost, linecodin->Array , LINE_CODING_STRUCTURE_SIZE );
+}
+
+/**
+* @brief This function prepares the state before issuing the class specific commands
+* @param None
+* @retval None
+*/
+USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+ if(phost->gState == HOST_CLASS)
+ {
+ CDC_Handle->state = CDC_SET_LINE_CODING_STATE;
+ CDC_Handle->pUserLineCoding = linecodin;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
+#endif
+ }
+ return USBH_OK;
+}
+
+/**
+* @brief This function prepares the state before issuing the class specific commands
+* @param None
+* @retval None
+*/
+USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if((phost->gState == HOST_CLASS) ||(phost->gState == HOST_CLASS_REQUEST))
+ {
+ *linecodin = CDC_Handle->LineCoding;
+ return USBH_OK;
+ }
+ else
+ {
+ return USBH_FAIL;
+ }
+}
+
+/**
+ * @brief This function return last recieved data size
+ * @param None
+ * @retval None
+ */
+uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if(phost->gState == HOST_CLASS)
+ {
+ return USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/**
+ * @brief This function prepares the state before issuing the class specific commands
+ * @param None
+ * @retval None
+ */
+USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length)
+{
+ USBH_StatusTypeDef Status = USBH_BUSY;
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA))
+ {
+ CDC_Handle->pTxData = pbuff;
+ CDC_Handle->TxDataLength = length;
+ CDC_Handle->state = CDC_TRANSFER_DATA;
+ CDC_Handle->data_tx_state = CDC_SEND_DATA;
+ Status = USBH_OK;
+ }
+ return Status;
+}
+
+
+/**
+* @brief This function prepares the state before issuing the class specific commands
+* @param None
+* @retval None
+*/
+USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length)
+{
+ USBH_StatusTypeDef Status = USBH_BUSY;
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+
+ if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA))
+ {
+ CDC_Handle->pRxData = pbuff;
+ CDC_Handle->RxDataLength = length;
+ CDC_Handle->state = CDC_TRANSFER_DATA;
+ CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;
+ Status = USBH_OK;
+ }
+ return Status;
+}
+
+/**
+* @brief The function is responsible for sending data to the device
+* @param pdev: Selected device
+* @retval None
+*/
+static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+ USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
+
+ switch(CDC_Handle->data_tx_state)
+ {
+
+ case CDC_SEND_DATA:
+ if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize)
+ {
+ USBH_BulkSendData (phost,
+ CDC_Handle->pTxData,
+ CDC_Handle->DataItf.OutEpSize,
+ CDC_Handle->DataItf.OutPipe,
+ 1);
+ }
+ else
+ {
+ USBH_BulkSendData (phost,
+ CDC_Handle->pTxData,
+ CDC_Handle->TxDataLength,
+ CDC_Handle->DataItf.OutPipe,
+ 1);
+ }
+
+ CDC_Handle->data_tx_state = CDC_SEND_DATA_WAIT;
+
+ break;
+
+ case CDC_SEND_DATA_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.OutPipe);
+
+ /*Check the status done for transmssion*/
+ if(URB_Status == USBH_URB_DONE )
+ {
+ if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize)
+ {
+ CDC_Handle->TxDataLength -= CDC_Handle->DataItf.OutEpSize ;
+ CDC_Handle->pTxData += CDC_Handle->DataItf.OutEpSize;
+ }
+ else
+ {
+ CDC_Handle->TxDataLength = 0;
+ }
+
+ if( CDC_Handle->TxDataLength > 0)
+ {
+ CDC_Handle->data_tx_state = CDC_SEND_DATA;
+ }
+ else
+ {
+ CDC_Handle->data_tx_state = CDC_IDLE;
+ USBH_CDC_TransmitCallback(phost);
+
+ }
+ }
+ else if( URB_Status == USBH_URB_NOTREADY )
+ {
+ CDC_Handle->data_tx_state = CDC_SEND_DATA;
+ }
+ break;
+ default:
+ break;
+ }
+}
+/**
+* @brief This function responsible for reception of data from the device
+* @param pdev: Selected device
+* @retval None
+*/
+
+static void CDC_ProcessReception(USBH_HandleTypeDef *phost)
+{
+ CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData;
+ USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
+ uint16_t length;
+
+ switch(CDC_Handle->data_rx_state)
+ {
+
+ case CDC_RECEIVE_DATA:
+
+ USBH_BulkReceiveData (phost,
+ CDC_Handle->pRxData,
+ CDC_Handle->DataItf.InEpSize,
+ CDC_Handle->DataItf.InPipe);
+
+ CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;
+
+ break;
+
+ case CDC_RECEIVE_DATA_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe);
+
+ /*Check the status done for reception*/
+ if(URB_Status == USBH_URB_DONE )
+ {
+ length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);
+
+ if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize))
+ {
+ CDC_Handle->RxDataLength -= length ;
+ CDC_Handle->pRxData += length;
+ CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;
+ }
+ else
+ {
+ CDC_Handle->data_rx_state = CDC_IDLE;
+ USBH_CDC_ReceiveCallback(phost);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+* @brief The function informs user that data have been received
+* @param pdev: Selected device
+* @retval None
+*/
+__weak void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost)
+{
+
+}
+
+ /**
+* @brief The function informs user that data have been sent
+* @param pdev: Selected device
+* @retval None
+*/
+__weak void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
+{
+
+}
+
+ /**
+* @brief The function informs user that Settings have been changed
+* @param pdev: Selected device
+* @retval None
+*/
+__weak void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost)
+{
+
+}
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Inc/usbh_hid.h b/stmhal/usbhost/Class/HID/Inc/usbh_hid.h new file mode 100644 index 000000000..38302ad0d --- /dev/null +++ b/stmhal/usbhost/Class/HID/Inc/usbh_hid.h @@ -0,0 +1,341 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_hid.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_HID_H
+#define __USBH_HID_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+#include "usbh_hid_mouse.h"
+#include "usbh_hid_keybd.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_CORE
+ * @brief This file is the Header file for USBH_HID_CORE.c
+ * @{
+ */
+
+
+/** @defgroup USBH_HID_CORE_Exported_Types
+ * @{
+ */
+
+#define HID_MIN_POLL 10
+#define HID_REPORT_SIZE 16
+#define HID_MAX_USAGE 10
+#define HID_MAX_NBR_REPORT_FMT 10
+#define HID_QUEUE_SIZE 10
+
+#define HID_ITEM_LONG 0xFE
+
+#define HID_ITEM_TYPE_MAIN 0x00
+#define HID_ITEM_TYPE_GLOBAL 0x01
+#define HID_ITEM_TYPE_LOCAL 0x02
+#define HID_ITEM_TYPE_RESERVED 0x03
+
+
+#define HID_MAIN_ITEM_TAG_INPUT 0x08
+#define HID_MAIN_ITEM_TAG_OUTPUT 0x09
+#define HID_MAIN_ITEM_TAG_COLLECTION 0x0A
+#define HID_MAIN_ITEM_TAG_FEATURE 0x0B
+#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0C
+
+
+#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00
+#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01
+#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02
+#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03
+#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04
+#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05
+#define HID_GLOBAL_ITEM_TAG_UNIT 0x06
+#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07
+#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08
+#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09
+#define HID_GLOBAL_ITEM_TAG_PUSH 0x0A
+#define HID_GLOBAL_ITEM_TAG_POP 0x0B
+
+
+#define HID_LOCAL_ITEM_TAG_USAGE 0x00
+#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01
+#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05
+#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07
+#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08
+#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09
+#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A
+
+
+/* States for HID State Machine */
+typedef enum
+{
+ HID_INIT= 0,
+ HID_IDLE,
+ HID_SEND_DATA,
+ HID_BUSY,
+ HID_GET_DATA,
+ HID_SYNC,
+ HID_POLL,
+ HID_ERROR,
+}
+HID_StateTypeDef;
+
+typedef enum
+{
+ HID_REQ_INIT = 0,
+ HID_REQ_IDLE,
+ HID_REQ_GET_REPORT_DESC,
+ HID_REQ_GET_HID_DESC,
+ HID_REQ_SET_IDLE,
+ HID_REQ_SET_PROTOCOL,
+ HID_REQ_SET_REPORT,
+
+}
+HID_CtlStateTypeDef;
+
+typedef enum
+{
+ HID_MOUSE = 0x01,
+ HID_KEYBOARD = 0x02,
+ HID_UNKNOWN = 0xFF,
+}
+HID_TypeTypeDef;
+
+
+typedef struct _HID_ReportData
+{
+ uint8_t ReportID;
+ uint8_t ReportType;
+ uint16_t UsagePage;
+ uint32_t Usage[HID_MAX_USAGE];
+ uint32_t NbrUsage;
+ uint32_t UsageMin;
+ uint32_t UsageMax;
+ int32_t LogMin;
+ int32_t LogMax;
+ int32_t PhyMin;
+ int32_t PhyMax;
+ int32_t UnitExp;
+ uint32_t Unit;
+ uint32_t ReportSize;
+ uint32_t ReportCnt;
+ uint32_t Flag;
+ uint32_t PhyUsage;
+ uint32_t AppUsage;
+ uint32_t LogUsage;
+}
+HID_ReportDataTypeDef;
+
+typedef struct _HID_ReportIDTypeDef {
+ uint8_t Size; /* Report size return by the device id */
+ uint8_t ReportID; /* Report Id */
+ uint8_t Type; /* Report Type (INPUT/OUTPUT/FEATURE) */
+} HID_ReportIDTypeDef;
+
+typedef struct _HID_CollectionTypeDef
+{
+ uint32_t Usage;
+ uint8_t Type;
+ struct _HID_CollectionTypeDef *NextPtr;
+} HID_CollectionTypeDef;
+
+
+typedef struct _HID_AppCollectionTypeDef {
+ uint32_t Usage;
+ uint8_t Type;
+ uint8_t NbrReportFmt;
+ HID_ReportDataTypeDef ReportData[HID_MAX_NBR_REPORT_FMT];
+} HID_AppCollectionTypeDef;
+
+
+typedef struct _HIDDescriptor
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */
+ uint8_t bCountryCode; /* specifies the transfer type. */
+ uint8_t bNumDescriptors; /* specifies the transfer type. */
+ uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */
+ uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */
+}
+HID_DescTypeDef;
+
+
+typedef struct
+{
+ uint8_t *buf;
+ uint16_t head;
+ uint16_t tail;
+ uint16_t size;
+ uint8_t lock;
+} FIFO_TypeDef;
+
+
+/* Structure for HID process */
+typedef struct _HID_Process
+{
+ uint8_t OutPipe;
+ uint8_t InPipe;
+ HID_StateTypeDef state;
+ uint8_t OutEp;
+ uint8_t InEp;
+ HID_CtlStateTypeDef ctl_state;
+ FIFO_TypeDef fifo;
+ uint8_t *pData;
+ uint16_t length;
+ uint8_t ep_addr;
+ uint16_t poll;
+ uint16_t timer;
+ uint8_t DataReady;
+ HID_DescTypeDef HID_Desc;
+ USBH_StatusTypeDef ( * Init)(USBH_HandleTypeDef *phost);
+}
+HID_HandleTypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_CORE_Exported_Defines
+ * @{
+ */
+
+#define USB_HID_GET_REPORT 0x01
+#define USB_HID_GET_IDLE 0x02
+#define USB_HID_GET_PROTOCOL 0x03
+#define USB_HID_SET_REPORT 0x09
+#define USB_HID_SET_IDLE 0x0A
+#define USB_HID_SET_PROTOCOL 0x0B
+
+
+
+
+/* HID Class Codes */
+#define USB_HID_CLASS 0x03
+
+/* Interface Descriptor field values for HID Boot Protocol */
+#define HID_BOOT_CODE 0x01
+#define HID_KEYBRD_BOOT_CODE 0x01
+#define HID_MOUSE_BOOT_CODE 0x02
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_CORE_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_CORE_Exported_Variables
+ * @{
+ */
+extern USBH_ClassTypeDef HID_Class;
+#define USBH_HID_CLASS &HID_Class
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_CORE_Exported_FunctionsPrototype
+ * @{
+ */
+
+USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost,
+ uint8_t reportType,
+ uint8_t reportId,
+ uint8_t* reportBuff,
+ uint8_t reportLen);
+
+USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
+ uint8_t reportType,
+ uint8_t reportId,
+ uint8_t* reportBuff,
+ uint8_t reportLen);
+
+USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost,
+ uint16_t length);
+
+USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost,
+ uint16_t length);
+
+USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost,
+ uint8_t duration,
+ uint8_t reportId);
+
+USBH_StatusTypeDef USBH_HID_SetProtocol (USBH_HandleTypeDef *phost,
+ uint8_t protocol);
+
+void USBH_HID_EventCallback(USBH_HandleTypeDef *phost);
+
+HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost);
+
+void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size);
+
+uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes);
+
+uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes);
+
+/**
+ * @}
+ */
+
+
+#endif /* __USBH_HID_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/HID/Inc/usbh_hid_keybd.h b/stmhal/usbhost/Class/HID/Inc/usbh_hid_keybd.h new file mode 100644 index 000000000..dc72ebb26 --- /dev/null +++ b/stmhal/usbhost/Class/HID/Inc/usbh_hid_keybd.h @@ -0,0 +1,318 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_keybd.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_hid_keybd.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive -----------------------------------------------*/
+#ifndef __USBH_HID_KEYBD_H
+#define __USBH_HID_KEYBD_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid.h"
+#include "usbh_hid_keybd.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_KEYBD
+ * @brief This file is the Header file for USBH_HID_KEYBD.c
+ * @{
+ */
+
+
+/** @defgroup USBH_HID_KEYBD_Exported_Types
+ * @{
+ */
+#define KEY_NONE 0x00
+#define KEY_ERRORROLLOVER 0x01
+#define KEY_POSTFAIL 0x02
+#define KEY_ERRORUNDEFINED 0x03
+#define KEY_A 0x04
+#define KEY_B 0x05
+#define KEY_C 0x06
+#define KEY_D 0x07
+#define KEY_E 0x08
+#define KEY_F 0x09
+#define KEY_G 0x0A
+#define KEY_H 0x0B
+#define KEY_I 0x0C
+#define KEY_J 0x0D
+#define KEY_K 0x0E
+#define KEY_L 0x0F
+#define KEY_M 0x10
+#define KEY_N 0x11
+#define KEY_O 0x12
+#define KEY_P 0x13
+#define KEY_Q 0x14
+#define KEY_R 0x15
+#define KEY_S 0x16
+#define KEY_T 0x17
+#define KEY_U 0x18
+#define KEY_V 0x19
+#define KEY_W 0x1A
+#define KEY_X 0x1B
+#define KEY_Y 0x1C
+#define KEY_Z 0x1D
+#define KEY_1_EXCLAMATION_MARK 0x1E
+#define KEY_2_AT 0x1F
+#define KEY_3_NUMBER_SIGN 0x20
+#define KEY_4_DOLLAR 0x21
+#define KEY_5_PERCENT 0x22
+#define KEY_6_CARET 0x23
+#define KEY_7_AMPERSAND 0x24
+#define KEY_8_ASTERISK 0x25
+#define KEY_9_OPARENTHESIS 0x26
+#define KEY_0_CPARENTHESIS 0x27
+#define KEY_ENTER 0x28
+#define KEY_ESCAPE 0x29
+#define KEY_BACKSPACE 0x2A
+#define KEY_TAB 0x2B
+#define KEY_SPACEBAR 0x2C
+#define KEY_MINUS_UNDERSCORE 0x2D
+#define KEY_EQUAL_PLUS 0x2E
+#define KEY_OBRACKET_AND_OBRACE 0x2F
+#define KEY_CBRACKET_AND_CBRACE 0x30
+#define KEY_BACKSLASH_VERTICAL_BAR 0x31
+#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32
+#define KEY_SEMICOLON_COLON 0x33
+#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34
+#define KEY_GRAVE ACCENT AND TILDE 0x35
+#define KEY_COMMA_AND_LESS 0x36
+#define KEY_DOT_GREATER 0x37
+#define KEY_SLASH_QUESTION 0x38
+#define KEY_CAPS LOCK 0x39
+#define KEY_F1 0x3A
+#define KEY_F2 0x3B
+#define KEY_F3 0x3C
+#define KEY_F4 0x3D
+#define KEY_F5 0x3E
+#define KEY_F6 0x3F
+#define KEY_F7 0x40
+#define KEY_F8 0x41
+#define KEY_F9 0x42
+#define KEY_F10 0x43
+#define KEY_F11 0x44
+#define KEY_F12 0x45
+#define KEY_PRINTSCREEN 0x46
+#define KEY_SCROLL LOCK 0x47
+#define KEY_PAUSE 0x48
+#define KEY_INSERT 0x49
+#define KEY_HOME 0x4A
+#define KEY_PAGEUP 0x4B
+#define KEY_DELETE 0x4C
+#define KEY_END1 0x4D
+#define KEY_PAGEDOWN 0x4E
+#define KEY_RIGHTARROW 0x4F
+#define KEY_LEFTARROW 0x50
+#define KEY_DOWNARROW 0x51
+#define KEY_UPARROW 0x52
+#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53
+#define KEY_KEYPAD_SLASH 0x54
+#define KEY_KEYPAD_ASTERIKS 0x55
+#define KEY_KEYPAD_MINUS 0x56
+#define KEY_KEYPAD_PLUS 0x57
+#define KEY_KEYPAD_ENTER 0x58
+#define KEY_KEYPAD_1_END 0x59
+#define KEY_KEYPAD_2_DOWN_ARROW 0x5A
+#define KEY_KEYPAD_3_PAGEDN 0x5B
+#define KEY_KEYPAD_4_LEFT_ARROW 0x5C
+#define KEY_KEYPAD_5 0x5D
+#define KEY_KEYPAD_6_RIGHT_ARROW 0x5E
+#define KEY_KEYPAD_7_HOME 0x5F
+#define KEY_KEYPAD_8_UP_ARROW 0x60
+#define KEY_KEYPAD_9_PAGEUP 0x61
+#define KEY_KEYPAD_0_INSERT 0x62
+#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63
+#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64
+#define KEY_APPLICATION 0x65
+#define KEY_POWER 0x66
+#define KEY_KEYPAD_EQUAL 0x67
+#define KEY_F13 0x68
+#define KEY_F14 0x69
+#define KEY_F15 0x6A
+#define KEY_F16 0x6B
+#define KEY_F17 0x6C
+#define KEY_F18 0x6D
+#define KEY_F19 0x6E
+#define KEY_F20 0x6F
+#define KEY_F21 0x70
+#define KEY_F22 0x71
+#define KEY_F23 0x72
+#define KEY_F24 0x73
+#define KEY_EXECUTE 0x74
+#define KEY_HELP 0x75
+#define KEY_MENU 0x76
+#define KEY_SELECT 0x77
+#define KEY_STOP 0x78
+#define KEY_AGAIN 0x79
+#define KEY_UNDO 0x7A
+#define KEY_CUT 0x7B
+#define KEY_COPY 0x7C
+#define KEY_PASTE 0x7D
+#define KEY_FIND 0x7E
+#define KEY_MUTE 0x7F
+#define KEY_VOLUME_UP 0x80
+#define KEY_VOLUME_DOWN 0x81
+#define KEY_LOCKING_CAPS_LOCK 0x82
+#define KEY_LOCKING_NUM_LOCK 0x83
+#define KEY_LOCKING_SCROLL_LOCK 0x84
+#define KEY_KEYPAD_COMMA 0x85
+#define KEY_KEYPAD_EQUAL_SIGN 0x86
+#define KEY_INTERNATIONAL1 0x87
+#define KEY_INTERNATIONAL2 0x88
+#define KEY_INTERNATIONAL3 0x89
+#define KEY_INTERNATIONAL4 0x8A
+#define KEY_INTERNATIONAL5 0x8B
+#define KEY_INTERNATIONAL6 0x8C
+#define KEY_INTERNATIONAL7 0x8D
+#define KEY_INTERNATIONAL8 0x8E
+#define KEY_INTERNATIONAL9 0x8F
+#define KEY_LANG1 0x90
+#define KEY_LANG2 0x91
+#define KEY_LANG3 0x92
+#define KEY_LANG4 0x93
+#define KEY_LANG5 0x94
+#define KEY_LANG6 0x95
+#define KEY_LANG7 0x96
+#define KEY_LANG8 0x97
+#define KEY_LANG9 0x98
+#define KEY_ALTERNATE_ERASE 0x99
+#define KEY_SYSREQ 0x9A
+#define KEY_CANCEL 0x9B
+#define KEY_CLEAR 0x9C
+#define KEY_PRIOR 0x9D
+#define KEY_RETURN 0x9E
+#define KEY_SEPARATOR 0x9F
+#define KEY_OUT 0xA0
+#define KEY_OPER 0xA1
+#define KEY_CLEAR_AGAIN 0xA2
+#define KEY_CRSEL 0xA3
+#define KEY_EXSEL 0xA4
+#define KEY_KEYPAD_00 0xB0
+#define KEY_KEYPAD_000 0xB1
+#define KEY_THOUSANDS_SEPARATOR 0xB2
+#define KEY_DECIMAL_SEPARATOR 0xB3
+#define KEY_CURRENCY_UNIT 0xB4
+#define KEY_CURRENCY_SUB_UNIT 0xB5
+#define KEY_KEYPAD_OPARENTHESIS 0xB6
+#define KEY_KEYPAD_CPARENTHESIS 0xB7
+#define KEY_KEYPAD_OBRACE 0xB8
+#define KEY_KEYPAD_CBRACE 0xB9
+#define KEY_KEYPAD_TAB 0xBA
+#define KEY_KEYPAD_BACKSPACE 0xBB
+#define KEY_KEYPAD_A 0xBC
+#define KEY_KEYPAD_B 0xBD
+#define KEY_KEYPAD_C 0xBE
+#define KEY_KEYPAD_D 0xBF
+#define KEY_KEYPAD_E 0xC0
+#define KEY_KEYPAD_F 0xC1
+#define KEY_KEYPAD_XOR 0xC2
+#define KEY_KEYPAD_CARET 0xC3
+#define KEY_KEYPAD_PERCENT 0xC4
+#define KEY_KEYPAD_LESS 0xC5
+#define KEY_KEYPAD_GREATER 0xC6
+#define KEY_KEYPAD_AMPERSAND 0xC7
+#define KEY_KEYPAD_LOGICAL_AND 0xC8
+#define KEY_KEYPAD_VERTICAL_BAR 0xC9
+#define KEY_KEYPAD_LOGIACL_OR 0xCA
+#define KEY_KEYPAD_COLON 0xCB
+#define KEY_KEYPAD_NUMBER_SIGN 0xCC
+#define KEY_KEYPAD_SPACE 0xCD
+#define KEY_KEYPAD_AT 0xCE
+#define KEY_KEYPAD_EXCLAMATION_MARK 0xCF
+#define KEY_KEYPAD_MEMORY_STORE 0xD0
+#define KEY_KEYPAD_MEMORY_RECALL 0xD1
+#define KEY_KEYPAD_MEMORY_CLEAR 0xD2
+#define KEY_KEYPAD_MEMORY_ADD 0xD3
+#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4
+#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5
+#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6
+#define KEY_KEYPAD_PLUSMINUS 0xD7
+#define KEY_KEYPAD_CLEAR 0xD8
+#define KEY_KEYPAD_CLEAR_ENTRY 0xD9
+#define KEY_KEYPAD_BINARY 0xDA
+#define KEY_KEYPAD_OCTAL 0xDB
+#define KEY_KEYPAD_DECIMAL 0xDC
+#define KEY_KEYPAD_HEXADECIMAL 0xDD
+#define KEY_LEFTCONTROL 0xE0
+#define KEY_LEFTSHIFT 0xE1
+#define KEY_LEFTALT 0xE2
+#define KEY_LEFT_GUI 0xE3
+#define KEY_RIGHTCONTROL 0xE4
+#define KEY_RIGHTSHIFT 0xE5
+#define KEY_RIGHTALT 0xE6
+#define KEY_RIGHT_GUI 0xE7
+
+typedef struct
+{
+ uint8_t state;
+ uint8_t lctrl;
+ uint8_t lshift;
+ uint8_t lalt;
+ uint8_t lgui;
+ uint8_t rctrl;
+ uint8_t rshift;
+ uint8_t ralt;
+ uint8_t rgui;
+ uint8_t keys[6];
+}
+HID_KEYBD_Info_TypeDef;
+
+USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost);
+HID_KEYBD_Info_TypeDef *USBH_HID_GetKeybdInfo(USBH_HandleTypeDef *phost);
+uint8_t USBH_HID_GetASCIICode(HID_KEYBD_Info_TypeDef *info);
+
+/**
+ * @}
+ */
+
+#endif /* __USBH_HID_KEYBD_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/HID/Inc/usbh_hid_mouse.h b/stmhal/usbhost/Class/HID/Inc/usbh_hid_mouse.h new file mode 100644 index 000000000..3a87d1a2d --- /dev/null +++ b/stmhal/usbhost/Class/HID/Inc/usbh_hid_mouse.h @@ -0,0 +1,118 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_mouse.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_hid_mouse.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_HID_MOUSE_H
+#define __USBH_HID_MOUSE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_MOUSE
+ * @brief This file is the Header file for USBH_HID_MOUSE.c
+ * @{
+ */
+
+
+/** @defgroup USBH_HID_MOUSE_Exported_Types
+ * @{
+ */
+
+typedef struct _HID_MOUSE_Info
+{
+ uint8_t x;
+ uint8_t y;
+ uint8_t buttons[3];
+}
+HID_MOUSE_Info_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_MOUSE_Exported_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_MOUSE_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_MOUSE_Exported_Variables
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_MOUSE_Exported_FunctionsPrototype
+ * @{
+ */
+USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost);
+HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost);
+
+/**
+ * @}
+ */
+
+#endif /* __USBH_HID_MOUSE_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Inc/usbh_hid_parser.h b/stmhal/usbhost/Class/HID/Inc/usbh_hid_parser.h new file mode 100644 index 000000000..0bf5739af --- /dev/null +++ b/stmhal/usbhost/Class/HID/Inc/usbh_hid_parser.h @@ -0,0 +1,96 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_parser.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the header file of the usbh_hid_parser.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+#ifndef _HID_PARSER_H_
+#define _HID_PARSER_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid.h"
+#include "usbh_hid_usage.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_PARSER
+ * @brief This file is the Header file for USBH_HID_PARSER.c
+ * @{
+ */
+
+
+/** @defgroup USBH_HID_PARSER_Exported_Types
+ * @{
+ */
+typedef struct
+{
+ uint8_t *data;
+ uint32_t size;
+ uint8_t shift;
+ uint8_t count;
+ uint8_t sign;
+ uint32_t logical_min; /*min value device can return*/
+ uint32_t logical_max; /*max value device can return*/
+ uint32_t physical_min; /*min vale read can report*/
+ uint32_t physical_max; /*max value read can report*/
+ uint32_t resolution;
+}
+HID_Report_ItemTypedef;
+
+
+uint32_t HID_ReadItem (HID_Report_ItemTypedef *ri, uint8_t ndx);
+uint32_t HID_WriteItem(HID_Report_ItemTypedef *ri, uint32_t value, uint8_t ndx);
+
+
+/**
+ * @}
+ */
+
+#endif /* _HID_PARSER_H_ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Inc/usbh_hid_usage.h b/stmhal/usbhost/Class/HID/Inc/usbh_hid_usage.h new file mode 100644 index 000000000..e1f7762f3 --- /dev/null +++ b/stmhal/usbhost/Class/HID/Inc/usbh_hid_usage.h @@ -0,0 +1,191 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_keybd.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contain the USAGE page codes
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+#ifndef _HID_USAGE_H_
+#define _HID_USAGE_H_
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_USAGE
+ * @brief This file is the Header file for USBH_HID_USAGE.c
+ * @{
+ */
+
+
+/** @defgroup USBH_HID_USAGE_Exported_Types
+ * @{
+ */
+
+/****************************************************/
+/* HID 1.11 usage pages */
+/****************************************************/
+
+#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */
+/**** Top level pages */
+#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/
+#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */
+#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */
+#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */
+#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */
+#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */
+#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */
+#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */
+#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */
+#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */
+#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */
+#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */
+#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/
+/* 0E Reserved */
+#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */
+#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */
+/* 11-13 Reserved */
+#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */
+/* 15-1f Reserved */
+/**** END of top level pages */
+/* 25-3f Reserved */
+#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */
+/* 41-7F Reserved */
+/*80-83 Monitor pages USB Device Class Definition for Monitor Devices
+ 84-87 Power pages USB Device Class Definition for Power Devices */
+/* 88-8B Reserved */
+#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */
+#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */
+#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */
+#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */
+#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */
+#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */
+
+/****************************************************/
+/* Usage definitions for the "Generic Decktop" page */
+/****************************************************/
+#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */
+#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */
+#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */
+/* 03 Reserved */
+#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */
+#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */
+#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */
+#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */
+#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */
+/* 09-2F Reserved */
+#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */
+#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */
+#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */
+#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */
+#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */
+#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */
+#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */
+#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */
+#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */
+#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */
+#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */
+#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */
+#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */
+#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */
+#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */
+/* 3F Reserved */
+#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */
+#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */
+#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */
+#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */
+#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */
+#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */
+#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */
+#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */
+/* 48-7F Reserved */
+#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */
+#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */
+#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */
+#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */
+#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */
+#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */
+#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */
+#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */
+#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */
+#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */
+#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */
+#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */
+#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */
+#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */
+#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */
+#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */
+#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */
+#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */
+#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */
+#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */
+/* 94-9F Reserved */
+#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */
+#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */
+#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */
+#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */
+#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */
+#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */
+#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */
+#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */
+#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */
+/* A9-AF Reserved */
+#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */
+#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */
+#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */
+#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */
+#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */
+#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */
+#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */
+#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */
+/* B8-FFFF Reserved */
+
+/**
+ * @}
+ */
+
+#endif /* _HID_USAGE_H_ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Src/usbh_hid.c b/stmhal/usbhost/Class/HID/Src/usbh_hid.c new file mode 100644 index 000000000..a56f45c5c --- /dev/null +++ b/stmhal/usbhost/Class/HID/Src/usbh_hid.c @@ -0,0 +1,800 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the HID Layer Handlers for USB Host HID class.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * HID Class Description
+ * ===================================================================
+ * This module manages the MSC class V1.11 following the "Device Class Definition
+ * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
+ * This driver implements the following aspects of the specification:
+ * - The Boot Interface Subclass
+ * - The Mouse and Keyboard protocols
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid.h"
+#include "usbh_hid_parser.h"
+
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_HID_CLASS
+* @{
+*/
+
+/** @defgroup USBH_HID_CORE
+* @brief This file includes HID Layer Handlers for USB Host HID class.
+* @{
+*/
+
+/** @defgroup USBH_HID_CORE_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_CORE_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_CORE_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_CORE_Private_Variables
+* @{
+*/
+
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_CORE_Private_FunctionPrototypes
+* @{
+*/
+
+static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost);
+static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost);
+static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf);
+
+extern USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost);
+extern USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost);
+
+USBH_ClassTypeDef HID_Class =
+{
+ "HID",
+ USB_HID_CLASS,
+ USBH_HID_InterfaceInit,
+ USBH_HID_InterfaceDeInit,
+ USBH_HID_ClassRequest,
+ USBH_HID_Process,
+ USBH_HID_SOFProcess,
+ NULL,
+};
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_CORE_Private_Functions
+* @{
+*/
+
+
+/**
+ * @brief USBH_HID_InterfaceInit
+ * The function init the HID class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost)
+{
+ uint8_t max_ep;
+ uint8_t num = 0;
+ uint8_t interface;
+
+ USBH_StatusTypeDef status = USBH_FAIL ;
+ HID_HandleTypeDef *HID_Handle;
+
+ interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFF);
+
+ if(interface == 0xFF) /* No Valid Interface */
+ {
+ status = USBH_FAIL;
+ USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
+ }
+ else
+ {
+ USBH_SelectInterface (phost, interface);
+ phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc (sizeof(HID_HandleTypeDef));
+ HID_Handle = phost->pActiveClass->pData;
+ HID_Handle->state = HID_ERROR;
+
+ /*Decode Bootclass Protocl: Mouse or Keyboard*/
+ if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
+ {
+ USBH_UsrLog ("KeyBoard device found!");
+ HID_Handle->Init = USBH_HID_KeybdInit;
+ }
+ else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE)
+ {
+ USBH_UsrLog ("Mouse device found!");
+ HID_Handle->Init = USBH_HID_MouseInit;
+ }
+ else
+ {
+ USBH_UsrLog ("Protocol not supported.");
+ return USBH_FAIL;
+ }
+
+ HID_Handle->state = HID_INIT;
+ HID_Handle->ctl_state = HID_REQ_INIT;
+ HID_Handle->ep_addr = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress;
+ HID_Handle->length = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
+ HID_Handle->poll = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bInterval ;
+
+ if (HID_Handle->poll < HID_MIN_POLL)
+ {
+ HID_Handle->poll = HID_MIN_POLL;
+ }
+
+ /* Check fo available number of endpoints */
+ /* Find the number of EPs in the Interface Descriptor */
+ /* Choose the lower number in order not to overrun the buffer allocated */
+ max_ep = ( (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
+ phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints :
+ USBH_MAX_NUM_ENDPOINTS);
+
+
+ /* Decode endpoint IN and OUT address from interface descriptor */
+ for ( ;num < max_ep; num++)
+ {
+ if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress & 0x80)
+ {
+ HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
+ HID_Handle->InPipe =\
+ USBH_AllocPipe(phost, HID_Handle->InEp);
+
+ /* Open pipe for IN endpoint */
+ USBH_OpenPipe (phost,
+ HID_Handle->InPipe,
+ HID_Handle->InEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_INTR,
+ HID_Handle->length);
+
+ USBH_LL_SetToggle (phost, HID_Handle->InPipe, 0);
+
+ }
+ else
+ {
+ HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
+ HID_Handle->OutPipe =\
+ USBH_AllocPipe(phost, HID_Handle->OutEp);
+
+ /* Open pipe for OUT endpoint */
+ USBH_OpenPipe (phost,
+ HID_Handle->OutPipe,
+ HID_Handle->OutEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_INTR,
+ HID_Handle->length);
+
+ USBH_LL_SetToggle (phost, HID_Handle->OutPipe, 0);
+ }
+
+ }
+ status = USBH_OK;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_HID_InterfaceDeInit
+ * The function DeInit the Pipes used for the HID class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost )
+{
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ if(HID_Handle->InPipe != 0x00)
+ {
+ USBH_ClosePipe (phost, HID_Handle->InPipe);
+ USBH_FreePipe (phost, HID_Handle->InPipe);
+ HID_Handle->InPipe = 0; /* Reset the pipe as Free */
+ }
+
+ if(HID_Handle->OutPipe != 0x00)
+ {
+ USBH_ClosePipe(phost, HID_Handle->OutPipe);
+ USBH_FreePipe (phost, HID_Handle->OutPipe);
+ HID_Handle->OutPipe = 0; /* Reset the pipe as Free */
+ }
+
+ if(phost->pActiveClass->pData)
+ {
+ USBH_free (phost->pActiveClass->pData);
+ }
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_HID_ClassRequest
+ * The function is responsible for handling Standard requests
+ * for HID class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost)
+{
+
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_StatusTypeDef classReqStatus = USBH_BUSY;
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ /* Switch HID state machine */
+ switch (HID_Handle->ctl_state)
+ {
+ case HID_REQ_INIT:
+ case HID_REQ_GET_HID_DESC:
+
+ /* Get HID Desc */
+ if (USBH_HID_GetHIDDescriptor (phost, USB_HID_DESC_SIZE)== USBH_OK)
+ {
+
+ USBH_HID_ParseHIDDesc(&HID_Handle->HID_Desc, phost->device.Data);
+ HID_Handle->ctl_state = HID_REQ_GET_REPORT_DESC;
+ }
+
+ break;
+ case HID_REQ_GET_REPORT_DESC:
+
+
+ /* Get Report Desc */
+ if (USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength) == USBH_OK)
+ {
+ /* The decriptor is available in phost->device.Data */
+
+ HID_Handle->ctl_state = HID_REQ_SET_IDLE;
+ }
+
+ break;
+
+ case HID_REQ_SET_IDLE:
+
+ classReqStatus = USBH_HID_SetIdle (phost, 0, 0);
+
+ /* set Idle */
+ if (classReqStatus == USBH_OK)
+ {
+ HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
+ }
+ else if(classReqStatus == USBH_NOT_SUPPORTED)
+ {
+ HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
+ }
+ break;
+
+ case HID_REQ_SET_PROTOCOL:
+ /* set protocol */
+ if (USBH_HID_SetProtocol (phost, 0) == USBH_OK)
+ {
+ HID_Handle->ctl_state = HID_REQ_IDLE;
+
+ /* all requests performed*/
+ phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
+ status = USBH_OK;
+ }
+ break;
+
+ case HID_REQ_IDLE:
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_HID_Process
+ * The function is for managing state machine for HID data transfers
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_OK;
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ switch (HID_Handle->state)
+ {
+ case HID_INIT:
+ HID_Handle->Init(phost);
+ case HID_IDLE:
+ if(USBH_HID_GetReport (phost,
+ 0x01,
+ 0,
+ HID_Handle->pData,
+ HID_Handle->length) == USBH_OK)
+ {
+
+ fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
+ HID_Handle->state = HID_SYNC;
+ }
+
+ break;
+
+ case HID_SYNC:
+
+ /* Sync with start of Even Frame */
+ if(phost->Timer & 1)
+ {
+ HID_Handle->state = HID_GET_DATA;
+ }
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ break;
+
+ case HID_GET_DATA:
+
+ USBH_InterruptReceiveData(phost,
+ HID_Handle->pData,
+ HID_Handle->length,
+ HID_Handle->InPipe);
+
+ HID_Handle->state = HID_POLL;
+ HID_Handle->timer = phost->Timer;
+ HID_Handle->DataReady = 0;
+ break;
+
+ case HID_POLL:
+
+ if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_DONE)
+ {
+ if(HID_Handle->DataReady == 0)
+ {
+ fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
+ HID_Handle->DataReady = 1;
+ USBH_HID_EventCallback(phost);
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ }
+ else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */
+ {
+
+ /* Issue Clear Feature on interrupt IN endpoint */
+ if(USBH_ClrFeature(phost,
+ HID_Handle->ep_addr) == USBH_OK)
+ {
+ /* Change state to issue next IN token */
+ HID_Handle->state = HID_GET_DATA;
+ }
+ }
+
+
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_HID_SOFProcess
+ * The function is for managing the SOF Process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
+{
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ if(HID_Handle->state == HID_POLL)
+ {
+ if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
+ {
+ HID_Handle->state = HID_GET_DATA;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ }
+ return USBH_OK;
+}
+
+/**
+* @brief USBH_Get_HID_ReportDescriptor
+ * Issue report Descriptor command to the device. Once the response
+ * received, parse the report descriptor and update the status.
+ * @param phost: Host handle
+ * @param Length : HID Report Descriptor Length
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost,
+ uint16_t length)
+{
+
+ USBH_StatusTypeDef status;
+
+ status = USBH_GetDescriptor(phost,
+ USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
+ USB_DESC_HID_REPORT,
+ phost->device.Data,
+ length);
+
+ /* HID report descriptor is available in phost->device.Data.
+ In case of USB Boot Mode devices for In report handling ,
+ HID report descriptor parsing is not required.
+ In case, for supporting Non-Boot Protocol devices and output reports,
+ user may parse the report descriptor*/
+
+
+ return status;
+}
+
+/**
+ * @brief USBH_Get_HID_Descriptor
+ * Issue HID Descriptor command to the device. Once the response
+ * received, parse the report descriptor and update the status.
+ * @param phost: Host handle
+ * @param Length : HID Descriptor Length
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost,
+ uint16_t length)
+{
+
+ USBH_StatusTypeDef status;
+
+ status = USBH_GetDescriptor( phost,
+ USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
+ USB_DESC_HID,
+ phost->device.Data,
+ length);
+
+ return status;
+}
+
+/**
+ * @brief USBH_Set_Idle
+ * Set Idle State.
+ * @param phost: Host handle
+ * @param duration: Duration for HID Idle request
+ * @param reportId : Targetted report ID for Set Idle request
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost,
+ uint8_t duration,
+ uint8_t reportId)
+{
+
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
+ USB_REQ_TYPE_CLASS;
+
+
+ phost->Control.setup.b.bRequest = USB_HID_SET_IDLE;
+ phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId;
+
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = 0;
+
+ return USBH_CtlReq(phost, 0 , 0 );
+}
+
+
+/**
+ * @brief USBH_HID_Set_Report
+ * Issues Set Report
+ * @param phost: Host handle
+ * @param reportType : Report type to be sent
+ * @param reportId : Targetted report ID for Set Report request
+ * @param reportBuff : Report Buffer
+ * @param reportLen : Length of data report to be send
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost,
+ uint8_t reportType,
+ uint8_t reportId,
+ uint8_t* reportBuff,
+ uint8_t reportLen)
+{
+
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
+ USB_REQ_TYPE_CLASS;
+
+
+ phost->Control.setup.b.bRequest = USB_HID_SET_REPORT;
+ phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
+
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = reportLen;
+
+ return USBH_CtlReq(phost, reportBuff , reportLen );
+}
+
+
+/**
+ * @brief USBH_HID_GetReport
+ * retreive Set Report
+ * @param phost: Host handle
+ * @param reportType : Report type to be sent
+ * @param reportId : Targetted report ID for Set Report request
+ * @param reportBuff : Report Buffer
+ * @param reportLen : Length of data report to be send
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost,
+ uint8_t reportType,
+ uint8_t reportId,
+ uint8_t* reportBuff,
+ uint8_t reportLen)
+{
+
+ phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE |\
+ USB_REQ_TYPE_CLASS;
+
+
+ phost->Control.setup.b.bRequest = USB_HID_GET_REPORT;
+ phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
+
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = reportLen;
+
+ return USBH_CtlReq(phost, reportBuff , reportLen );
+}
+
+/**
+ * @brief USBH_Set_Protocol
+ * Set protocol State.
+ * @param phost: Host handle
+ * @param protocol : Set Protocol for HID : boot/report protocol
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost,
+ uint8_t protocol)
+{
+
+
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
+ USB_REQ_TYPE_CLASS;
+
+
+ phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL;
+ phost->Control.setup.b.wValue.w = protocol != 0 ? 0 : 1;
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = 0;
+
+ return USBH_CtlReq(phost, 0 , 0 );
+
+}
+
+/**
+ * @brief USBH_ParseHIDDesc
+ * This function Parse the HID descriptor
+ * @param desc: HID Descriptor
+ * @param buf: Buffer where the source descriptor is available
+ * @retval None
+ */
+static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf)
+{
+
+ desc->bLength = *(uint8_t *) (buf + 0);
+ desc->bDescriptorType = *(uint8_t *) (buf + 1);
+ desc->bcdHID = LE16 (buf + 2);
+ desc->bCountryCode = *(uint8_t *) (buf + 4);
+ desc->bNumDescriptors = *(uint8_t *) (buf + 5);
+ desc->bReportDescriptorType = *(uint8_t *) (buf + 6);
+ desc->wItemLength = LE16 (buf + 7);
+}
+
+/**
+ * @brief USBH_HID_GetDeviceType
+ * Return Device function.
+ * @param phost: Host handle
+ * @retval HID function: HID_MOUSE / HID_KEYBOARD
+ */
+HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost)
+{
+ HID_TypeTypeDef type = HID_UNKNOWN;
+
+ if(phost->gState == HOST_CLASS)
+ {
+
+ if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \
+ == HID_KEYBRD_BOOT_CODE)
+ {
+ type = HID_KEYBOARD;
+ }
+ else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \
+ == HID_MOUSE_BOOT_CODE)
+ {
+ type= HID_MOUSE;
+ }
+ }
+ return type;
+}
+
+/**
+ * @brief fifo_init
+ * Initialize FIFO.
+ * @param f: Fifo address
+ * @param buf: Fifo buffer
+ * @param size: Fifo Size
+ * @retval none
+ */
+void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size)
+{
+ f->head = 0;
+ f->tail = 0;
+ f->lock = 0;
+ f->size = size;
+ f->buf = buf;
+}
+
+/**
+ * @brief fifo_read
+ * Read from FIFO.
+ * @param f: Fifo address
+ * @param buf: read buffer
+ * @param nbytes: number of item to read
+ * @retval number of read items
+ */
+uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes)
+{
+ uint16_t i;
+ uint8_t * p;
+ p = buf;
+
+ if(f->lock == 0)
+ {
+ f->lock = 1;
+ for(i=0; i < nbytes; i++)
+ {
+ if( f->tail != f->head )
+ {
+ *p++ = f->buf[f->tail];
+ f->tail++;
+ if( f->tail == f->size )
+ {
+ f->tail = 0;
+ }
+ } else
+ {
+ f->lock = 0;
+ return i;
+ }
+ }
+ }
+ f->lock = 0;
+ return nbytes;
+}
+
+/**
+ * @brief fifo_write
+ * Read from FIFO.
+ * @param f: Fifo address
+ * @param buf: read buffer
+ * @param nbytes: number of item to write
+ * @retval number of written items
+ */
+uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes)
+{
+ uint16_t i;
+ const uint8_t * p;
+ p = buf;
+ if(f->lock == 0)
+ {
+ f->lock = 1;
+ for(i=0; i < nbytes; i++)
+ {
+ if( (f->head + 1 == f->tail) ||
+ ( (f->head + 1 == f->size) && (f->tail == 0)) )
+ {
+ f->lock = 0;
+ return i;
+ }
+ else
+ {
+ f->buf[f->head] = *p++;
+ f->head++;
+ if( f->head == f->size )
+ {
+ f->head = 0;
+ }
+ }
+ }
+ }
+ f->lock = 0;
+ return nbytes;
+}
+
+
+/**
+* @brief The function is a callback about HID Data events
+* @param phost: Selected device
+* @retval None
+*/
+__weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
+{
+
+}
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Src/usbh_hid_keybd.c b/stmhal/usbhost/Class/HID/Src/usbh_hid_keybd.c new file mode 100644 index 000000000..79104767b --- /dev/null +++ b/stmhal/usbhost/Class/HID/Src/usbh_hid_keybd.c @@ -0,0 +1,418 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_keybd.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the application layer for USB Host HID Keyboard handling
+ * QWERTY and AZERTY Keyboard are supported as per the selection in
+ * usbh_hid_keybd.h
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid_keybd.h"
+#include "usbh_hid_parser.h"
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_HID_CLASS
+* @{
+*/
+
+/** @defgroup USBH_HID_KEYBD
+* @brief This file includes HID Layer Handlers for USB Host HID class.
+* @{
+*/
+
+/** @defgroup USBH_HID_KEYBD_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_HID_KEYBD_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+#ifndef AZERTY_KEYBOARD
+ #define QWERTY_KEYBOARD
+#endif
+#define KBD_LEFT_CTRL 0x01
+#define KBD_LEFT_SHIFT 0x02
+#define KBD_LEFT_ALT 0x04
+#define KBD_LEFT_GUI 0x08
+#define KBD_RIGHT_CTRL 0x10
+#define KBD_RIGHT_SHIFT 0x20
+#define KBD_RIGHT_ALT 0x40
+#define KBD_RIGHT_GUI 0x80
+#define KBR_MAX_NBR_PRESSED 6
+
+/** @defgroup USBH_HID_KEYBD_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_HID_KEYBD_Private_FunctionPrototypes
+* @{
+*/
+static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost);
+/**
+* @}
+*/
+
+/** @defgroup USBH_HID_KEYBD_Private_Variables
+* @{
+*/
+
+HID_KEYBD_Info_TypeDef keybd_info;
+uint32_t keybd_report_data[2];
+
+static const HID_Report_ItemTypedef imp_0_lctrl={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 0, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_lshift={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 1, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_lalt={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 2, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_lgui={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 3, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_rctrl={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 4, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_rshift={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 5, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_ralt={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 6, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+static const HID_Report_ItemTypedef imp_0_rgui={
+ (uint8_t*)keybd_report_data+0, /*data*/
+ 1, /*size*/
+ 7, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+
+static const HID_Report_ItemTypedef imp_0_key_array={
+ (uint8_t*)keybd_report_data+2, /*data*/
+ 8, /*size*/
+ 0, /*shift*/
+ 6, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 101, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 101, /*max value device can report*/
+ 1 /*resolution*/
+};
+
+#ifdef QWERTY_KEYBOARD
+static const int8_t HID_KEYBRD_Key[] = {
+ '\0', '`', '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', '0', '-', '=', '\0', '\r',
+ '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u',
+ 'i', 'o', 'p', '[', ']', '\\',
+ '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j',
+ 'k', 'l', ';', '\'', '\0', '\n',
+ '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n',
+ 'm', ',', '.', '/', '\0', '\0',
+ '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '7', '4', '1',
+ '\0', '/', '8', '5', '2',
+ '0', '*', '9', '6', '3',
+ '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0'
+};
+
+static const int8_t HID_KEYBRD_ShiftKey[] = {
+ '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U',
+ 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G',
+ 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X',
+ 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+};
+
+#else
+
+static const int8_t HID_KEYBRD_Key[] = {
+ '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+ '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u',
+ 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g',
+ 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x',
+ 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0',
+ '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/',
+ '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0',
+ '\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+};
+
+static const int8_t HID_KEYBRD_ShiftKey[] = {
+ '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
+ 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K',
+ 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N',
+ '?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+};
+#endif
+
+static const uint8_t HID_KEYBRD_Codes[] = {
+ 0, 0, 0, 0, 31, 50, 48, 33,
+ 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */
+ 52, 51, 25, 26, 17, 20, 32, 21,
+ 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */
+ 28, 29, 42, 40, 41, 1, 53, 54,
+ 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */
+ 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */
+ 79, 84, 83, 90, 95, 100, 105, 106,
+ 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */
+ 96, 101, 99, 104, 45, 129, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */
+ 0, 0, 0, 0, 0, 107, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */
+ 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */
+};
+
+/**
+ * @brief USBH_HID_KeybdInit
+ * The function init the HID keyboard.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost)
+{
+ uint32_t x;
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ keybd_info.lctrl=keybd_info.lshift= 0;
+ keybd_info.lalt=keybd_info.lgui= 0;
+ keybd_info.rctrl=keybd_info.rshift= 0;
+ keybd_info.ralt=keybd_info.rgui=0;
+
+
+ for(x=0; x< (sizeof(keybd_report_data)/sizeof(uint32_t)); x++)
+ {
+ keybd_report_data[x]=0;
+ }
+
+ if(HID_Handle->length > (sizeof(keybd_report_data)/sizeof(uint32_t)))
+ {
+ HID_Handle->length = (sizeof(keybd_report_data)/sizeof(uint32_t));
+ }
+ HID_Handle->pData = (uint8_t*)keybd_report_data;
+ fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(keybd_report_data));
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_HID_GetKeybdInfo
+ * The function return keyboard information.
+ * @param phost: Host handle
+ * @retval keyboard information
+ */
+HID_KEYBD_Info_TypeDef *USBH_HID_GetKeybdInfo(USBH_HandleTypeDef *phost)
+{
+ if(USBH_HID_KeybdDecode(phost) == USBH_OK)
+ {
+ return &keybd_info;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/**
+ * @brief USBH_HID_KeybdDecode
+ * The function decode keyboard data.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost)
+{
+ uint8_t x;
+
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+ if(HID_Handle->length == 0)
+ {
+ return USBH_FAIL;
+ }
+ /*Fill report */
+ if(fifo_read(&HID_Handle->fifo, &keybd_report_data, HID_Handle->length) == HID_Handle->length)
+ {
+
+ keybd_info.lctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lctrl, 0);
+ keybd_info.lshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lshift, 0);
+ keybd_info.lalt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lalt, 0);
+ keybd_info.lgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lgui, 0);
+ keybd_info.rctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rctrl, 0);
+ keybd_info.rshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rshift, 0);
+ keybd_info.ralt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_ralt, 0);
+ keybd_info.rgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rgui, 0);
+
+ for(x=0; x < sizeof(keybd_info.keys); x++)
+ {
+ keybd_info.keys[x]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_key_array, x);
+ }
+
+ return USBH_OK;
+ }
+ return USBH_FAIL;
+}
+
+/**
+ * @brief USBH_HID_GetASCIICode
+ * The function decode keyboard data into ASCII characters.
+ * @param phost: Host handle
+ * @param info: Keyboard information
+ * @retval ASCII code
+ */
+uint8_t USBH_HID_GetASCIICode(HID_KEYBD_Info_TypeDef *info)
+{
+ uint8_t output;
+ if((info->lshift == 1) || (info->rshift))
+ {
+ output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[info->keys[0]]];
+ }
+ else
+ {
+ output = HID_KEYBRD_Key[HID_KEYBRD_Codes[info->keys[0]]];
+ }
+ return output;
+}
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/HID/Src/usbh_hid_mouse.c b/stmhal/usbhost/Class/HID/Src/usbh_hid_mouse.c new file mode 100644 index 000000000..0851714af --- /dev/null +++ b/stmhal/usbhost/Class/HID/Src/usbh_hid_mouse.c @@ -0,0 +1,267 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_mouse.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the application layer for USB Host HID Mouse Handling.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid_mouse.h"
+#include "usbh_hid_parser.h"
+
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_MOUSE
+ * @brief This file includes HID Layer Handlers for USB Host HID class.
+ * @{
+ */
+
+/** @defgroup USBH_HID_MOUSE_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_MOUSE_Private_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_MOUSE_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_MOUSE_Private_FunctionPrototypes
+ * @{
+ */
+static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost);
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_MOUSE_Private_Variables
+ * @{
+ */
+HID_MOUSE_Info_TypeDef mouse_info;
+uint32_t mouse_report_data[1];
+
+/* Structures defining how to access items in a HID mouse report */
+/* Access button 1 state. */
+static const HID_Report_ItemTypedef prop_b1={
+ (uint8_t *)mouse_report_data+0, /*data*/
+ 1, /*size*/
+ 0, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min value device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+
+/* Access button 2 state. */
+static const HID_Report_ItemTypedef prop_b2={
+ (uint8_t *)mouse_report_data+0, /*data*/
+ 1, /*size*/
+ 1, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min value device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+
+/* Access button 3 state. */
+static const HID_Report_ItemTypedef prop_b3={
+ (uint8_t *)mouse_report_data+0, /*data*/
+ 1, /*size*/
+ 2, /*shift*/
+ 0, /*count (only for array items)*/
+ 0, /*signed?*/
+ 0, /*min value read can return*/
+ 1, /*max value read can return*/
+ 0, /*min vale device can report*/
+ 1, /*max value device can report*/
+ 1 /*resolution*/
+};
+
+/* Access x coordinate change. */
+static const HID_Report_ItemTypedef prop_x={
+ (uint8_t *)mouse_report_data+1, /*data*/
+ 8, /*size*/
+ 0, /*shift*/
+ 0, /*count (only for array items)*/
+ 1, /*signed?*/
+ 0, /*min value read can return*/
+ 0xFFFF,/*max value read can return*/
+ 0, /*min vale device can report*/
+ 0xFFFF,/*max value device can report*/
+ 1 /*resolution*/
+};
+
+/* Access y coordinate change. */
+static const HID_Report_ItemTypedef prop_y={
+ (uint8_t *)mouse_report_data+2, /*data*/
+ 8, /*size*/
+ 0, /*shift*/
+ 0, /*count (only for array items)*/
+ 1, /*signed?*/
+ 0, /*min value read can return*/
+ 0xFFFF,/*max value read can return*/
+ 0, /*min vale device can report*/
+ 0xFFFF,/*max value device can report*/
+ 1 /*resolution*/
+};
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_MOUSE_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBH_HID_MouseInit
+ * The function init the HID mouse.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost)
+{
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ mouse_info.x=0;
+ mouse_info.y=0;
+ mouse_info.buttons[0]=0;
+ mouse_info.buttons[1]=0;
+ mouse_info.buttons[2]=0;
+
+ mouse_report_data[0]=0;
+
+ if(HID_Handle->length > sizeof(mouse_report_data))
+ {
+ HID_Handle->length = sizeof(mouse_report_data);
+ }
+ HID_Handle->pData = (uint8_t *)mouse_report_data;
+ fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(mouse_report_data));
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_HID_GetMouseInfo
+ * The function return mouse information.
+ * @param phost: Host handle
+ * @retval mouse information
+ */
+HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost)
+{
+ if(USBH_HID_MouseDecode(phost)== USBH_OK)
+ {
+ return &mouse_info;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/**
+ * @brief USBH_HID_MouseDecode
+ * The function decode mouse data.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost)
+{
+ HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData;
+
+ if(HID_Handle->length == 0)
+ {
+ return USBH_FAIL;
+ }
+ /*Fill report */
+ if(fifo_read(&HID_Handle->fifo, &mouse_report_data, HID_Handle->length) == HID_Handle->length)
+ {
+
+ /*Decode report */
+ mouse_info.x = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_x, 0);
+ mouse_info.y = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_y, 0);
+
+ mouse_info.buttons[0]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b1, 0);
+ mouse_info.buttons[1]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b2, 0);
+ mouse_info.buttons[2]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b3, 0);
+
+ return USBH_OK;
+ }
+ return USBH_FAIL;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/HID/Src/usbh_hid_parser.c b/stmhal/usbhost/Class/HID/Src/usbh_hid_parser.c new file mode 100644 index 000000000..a050f95e9 --- /dev/null +++ b/stmhal/usbhost/Class/HID/Src/usbh_hid_parser.c @@ -0,0 +1,235 @@ +/**
+ ******************************************************************************
+ * @file usbh_hid_parser.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the HID Layer Handlers for USB Host HID class.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_hid_parser.h"
+
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_HID_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_HID_PARSER
+ * @brief This file includes HID parsers for USB Host HID class.
+ * @{
+ */
+
+/** @defgroup USBH_HID_PARSER_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_PARSER_Private_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_PARSER_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_HID_PARSER_Private_FunctionPrototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_PARSER_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBH_HID_PARSER_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief HID_ReadItem
+ * The function read a report item.
+ * @param ri: report item
+ * @param ndx: report index
+* @retval status (0 : fail / otherwise: item value)
+ */
+uint32_t HID_ReadItem(HID_Report_ItemTypedef *ri, uint8_t ndx)
+{
+ uint32_t val=0;
+ uint32_t x=0;
+ uint32_t bofs;
+ uint8_t *data=ri->data;
+ uint8_t shift=ri->shift;
+
+ /* get the logical value of the item */
+
+ /* if this is an array, wee may need to offset ri->data.*/
+ if (ri->count > 0)
+ {
+ /* If app tries to read outside of the array. */
+ if (ri->count <= ndx)
+ {
+ return(0);
+ }
+
+ /* calculate bit offset */
+ bofs = ndx*ri->size;
+ bofs += shift;
+ /* calculate byte offset + shift pair from bit offset. */
+ data+=bofs/8;
+ shift=(uint8_t)(bofs%8);
+ }
+ /* read data bytes in little endian order */
+ for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++)
+ {
+ val=(uint32_t)(*data << (x*8));
+ }
+ val=(val >> shift) & ((1<<ri->size)-1);
+
+ if (val < ri->logical_min || val > ri->logical_max)
+ {
+ return(0);
+ }
+
+ /* convert logical value to physical value */
+ /* See if the number is negative or not. */
+ if ((ri->sign) && (val & (1<<(ri->size-1))))
+ {
+ /* yes, so sign extend value to 32 bits. */
+ int vs=(int)((-1 & ~((1<<(ri->size))-1)) | val);
+
+ if(ri->resolution == 1)
+ {
+ return((uint32_t)vs);
+ }
+ return((uint32_t)(vs*ri->resolution));
+ }
+ else
+ {
+ if(ri->resolution == 1)
+ {
+ return(val);
+ }
+ return(val*ri->resolution);
+ }
+}
+
+/**
+ * @brief HID_WriteItem
+ * The function write a report item.
+ * @param ri: report item
+ * @param ndx: report index
+ * @retval status (1: fail/ 0 : Ok)
+ */
+uint32_t HID_WriteItem(HID_Report_ItemTypedef *ri, uint32_t value, uint8_t ndx)
+{
+ uint32_t x;
+ uint32_t mask;
+ uint32_t bofs;
+ uint8_t *data=ri->data;
+ uint8_t shift=ri->shift;
+
+ if (value < ri->physical_min || value > ri->physical_max)
+ {
+ return(1);
+ }
+
+ /* if this is an array, wee may need to offset ri->data.*/
+ if (ri->count > 0)
+ {
+ /* If app tries to read outside of the array. */
+ if (ri->count >= ndx)
+ {
+ return(0);
+ }
+ /* calculate bit offset */
+ bofs = ndx*ri->size;
+ bofs += shift;
+ /* calculate byte offset + shift pair from bit offset. */
+ data+=bofs/8;
+ shift=(uint8_t)(bofs%8);
+
+ }
+
+ /* Convert physical value to logical value. */
+ if (ri->resolution != 1)
+ {
+ value=value/ri->resolution;
+ }
+
+ /* Write logical value to report in little endian order. */
+ mask=(uint32_t)((1<<ri->size)-1);
+ value = (value & mask) << shift;
+
+ for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++)
+ {
+ *(ri->data+x)=(uint8_t)((*(ri->data+x) & ~(mask>>(x*8))) | ((value>>(x*8)) & (mask>>(x*8))));
+ }
+ return(0);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h new file mode 100644 index 000000000..ea173a7da --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h @@ -0,0 +1,222 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_msc_core.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_MSC_H
+#define __USBH_MSC_H
+
+/* 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_core.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;
+
+#define MAX_SUPPORTED_LUN 2
+
+/* 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);
+/**
+ * @}
+ */
+
+#endif /* __USBH_MSC_H */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h new file mode 100644 index 000000000..5422c80eb --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h @@ -0,0 +1,233 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc_bot.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief Header file for usbh_msc_bot.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_MSC_BOT_H__
+#define __USBH_MSC_BOT_H__
+
+/* 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_core.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 continously, 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);
+
+
+
+/**
+ * @}
+ */
+
+#endif //__USBH_MSC_BOT_H__
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h new file mode 100644 index 000000000..76b51902a --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h @@ -0,0 +1,218 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc_scsi.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief Header file for usbh_msc_scsi.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_MSC_SCSI_H__
+#define __USBH_MSC_SCSI_H__
+
+/* 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);
+
+
+/**
+ * @}
+ */
+
+#endif //__USBH_MSC_SCSI_H__
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc.c new file mode 100644 index 000000000..53a2cd81d --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc.c @@ -0,0 +1,795 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @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>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "usbh_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 = 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 = 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 = 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 */
+ if(USBH_MSC_BOT_REQ_GetMaxLUN(phost, (uint8_t *)&MSC_Handle->max_lun) == 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;
+ }
+ status = USBH_OK;
+ }
+ 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 = 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 + 10000;
+
+ 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 ("Mass Storage 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 ("Mass Storage 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 ("Mass Storage Device capacity : %lu MB", \
+ (int32_t)((MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)/1024/1024));
+ 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)
+ {
+ 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 ("Mass Storage 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 = 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 ("Mass Storage 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 = 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 = 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 = 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 = 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 = 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 + (10000 * length);
+ while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (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 = 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 + (10000 * length);
+ while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (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****/
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c new file mode 100644 index 000000000..5489ce297 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c @@ -0,0 +1,633 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc_bot.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file includes the BOT protocol related functions
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_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 = 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 = 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)
+ {
+ /* Adjudt 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)
+ {
+ /* Adjudt 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)
+ {
+ /* Re-send 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 = 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 = phost->pActiveClass->pData;
+ BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED;
+
+ /*Checking if the transfer length is diffrent 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****/
+
+
+
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c new file mode 100644 index 000000000..5d069b40a --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c @@ -0,0 +1,458 @@ +/**
+ ******************************************************************************
+ * @file usbh_msc_scsi.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file implements the SCSI commands
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_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 = 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 = 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 = 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 = 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 = 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]);
+
+
+ /*Tranfer 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 = 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]);
+
+
+ /*Tranfer 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****/
+
+
+
diff --git a/stmhal/usbhost/Class/MTP/Inc/usbh_mtp.h b/stmhal/usbhost/Class/MTP/Inc/usbh_mtp.h new file mode 100644 index 000000000..704a410fd --- /dev/null +++ b/stmhal/usbhost/Class/MTP/Inc/usbh_mtp.h @@ -0,0 +1,263 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_mtp.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_MTP_CORE_H
+#define __USBH_MTP_CORE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_mtp_ptp.h"
+#include "usbh_core.h"
+
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_MTP_CLASS
+* @{
+*/
+
+/** @defgroup USBH_MTP_CORE
+* @brief This file is the Header file for USBH_MTP_CORE.c
+* @{
+*/
+
+
+
+
+/*Communication Class codes*/
+#define USB_MTP_CLASS 0x06 /* Still Image Class)*/
+#define MTP_MAX_STORAGE_UNITS_NBR PTP_MAX_STORAGE_UNITS_NBR
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_MTP_CORE_Exported_Types
+* @{
+*/
+typedef enum
+{
+ MTP_IDLE = 0,
+ MTP_GETDEVICEINFO ,
+ MTP_OPENSESSION ,
+ MTP_CLOSESESSION ,
+ MTP_GETSTORAGEIDS ,
+ MTP_GETSTORAGEINFO ,
+}
+MTP_StateTypeDef;
+
+
+typedef enum
+{
+ MTP_EVENTS_INIT = 0,
+ MTP_EVENTS_GETDATA ,
+}
+MTP_EventsStateTypeDef;
+
+
+typedef struct
+{
+ MTP_EventsStateTypeDef state;
+ uint32_t timer;
+ uint16_t poll;
+ PTP_EventContainerTypedef container;
+}
+MTP_EventHandleTypedef;
+
+typedef struct
+{
+
+ uint32_t CurrentStorageId;
+ uint32_t ObjectFormatCode;
+ uint32_t CurrentObjectHandler;
+ uint8_t ObjectHandlerNbr;
+ uint32_t Objdepth;
+}
+MTP_ParamsTypedef;
+
+
+typedef struct
+{
+ PTP_DeviceInfoTypedef devinfo;
+ PTP_StorageIDsTypedef storids;
+ PTP_StorageInfoTypedef storinfo[MTP_MAX_STORAGE_UNITS_NBR];
+ PTP_ObjectHandlesTypedef Handles;
+}
+MTP_InfoTypedef;
+
+/* Structure for MTP process */
+typedef struct _MTP_Process
+{
+ MTP_InfoTypedef info;
+ MTP_ParamsTypedef params;
+
+ uint8_t DataInPipe;
+ uint8_t DataOutPipe;
+ uint8_t NotificationPipe;
+
+ uint8_t DataOutEp;
+ uint8_t DataInEp;
+ uint8_t NotificationEp;
+
+ uint16_t DataOutEpSize;
+ uint16_t DataInEpSize;
+ uint16_t NotificationEpSize;
+ MTP_StateTypeDef state;
+ MTP_EventHandleTypedef events;
+ PTP_HandleTypeDef ptp;
+ uint32_t current_storage_unit;
+ uint32_t is_ready;
+}
+MTP_HandleTypeDef;
+
+#define MTP_StorageInfoTypedef PTP_StorageInfoTypedef
+#define MTP_ObjectHandlesTypedef PTP_ObjectHandlesTypedef
+#define MTP_ObjectInfoTypedef PTP_ObjectInfoTypedef
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_CORE_Exported_Defines
+* @{
+*/
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_CORE_Exported_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_CORE_Exported_Variables
+* @{
+*/
+extern USBH_ClassTypeDef MTP_Class;
+#define USBH_MTP_CLASS &MTP_Class
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_CORE_Exported_FunctionsPrototype
+* @{
+*/
+uint8_t USBH_MTP_IsReady (USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_MTP_SelectStorage (USBH_HandleTypeDef *phost, uint8_t storage_idx);
+USBH_StatusTypeDef USBH_MTP_GetNumStorage (USBH_HandleTypeDef *phost, uint8_t *storage_num);
+USBH_StatusTypeDef USBH_MTP_GetNumObjects (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ uint32_t* numobs);
+USBH_StatusTypeDef USBH_MTP_GetStorageInfo (USBH_HandleTypeDef *phost,
+ uint8_t storage_idx,
+ MTP_StorageInfoTypedef *info);
+
+USBH_StatusTypeDef USBH_MTP_GetObjectHandles (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ PTP_ObjectHandlesTypedef* objecthandles);
+
+USBH_StatusTypeDef USBH_MTP_GetObjectInfo (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ PTP_ObjectInfoTypedef* objectinfo);
+
+USBH_StatusTypeDef USBH_MTP_DeleteObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t objectformatcode);
+
+USBH_StatusTypeDef USBH_MTP_GetObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object);
+
+USBH_StatusTypeDef USBH_MTP_GetPartialObject(USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t maxbytes,
+ uint8_t *object,
+ uint32_t *len);
+
+USBH_StatusTypeDef USBH_MTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost,
+ uint16_t ofc,
+ uint32_t *propnum,
+ uint16_t *props);
+
+USBH_StatusTypeDef USBH_MTP_GetObjectPropDesc (USBH_HandleTypeDef *phost,
+ uint16_t opc,
+ uint16_t ofc,
+ PTP_ObjectPropDescTypeDef *opd);
+
+USBH_StatusTypeDef USBH_MTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ MTP_PropertiesTypedef *pprops,
+ uint32_t *nrofprops);
+
+USBH_StatusTypeDef USBH_MTP_SendObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object,
+ uint32_t size);
+
+USBH_StatusTypeDef USBH_MTP_GetDevicePropDesc (USBH_HandleTypeDef *phost,
+ uint16_t propcode,
+ PTP_DevicePropDescTypdef* devicepropertydesc);
+
+void USBH_MTP_EventsCallback(USBH_HandleTypeDef *phost, uint32_t event, uint32_t param);
+/**
+* @}
+*/
+
+
+#endif /* __USBH_MTP_CORE_H */
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h b/stmhal/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h new file mode 100644 index 000000000..3fbddd87b --- /dev/null +++ b/stmhal/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h @@ -0,0 +1,1038 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp_ptp.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief Header file for usbh_mtp_ptp.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_MTP_PTP_H__
+#define __USBH_MTP_PTP_H__
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+
+/** @addtogroup USBH_LIB
+ * @{
+ */
+
+/** @addtogroup USBH_CLASS
+ * @{
+ */
+
+/** @addtogroup USBH_MTP_PTP_CLASS
+ * @{
+ */
+
+/** @defgroup USBH_MTP_PTP
+ * @brief This file is the Header file for usbh_mtp_ptp.c
+ * @{
+ */
+
+
+/* Operation Codes */
+
+/* PTP v1.0 operation codes */
+#define PTP_OC_Undefined 0x1000
+#define PTP_OC_GetDeviceInfo 0x1001
+#define PTP_OC_OpenSession 0x1002
+#define PTP_OC_CloseSession 0x1003
+#define PTP_OC_GetStorageIDs 0x1004
+#define PTP_OC_GetStorageInfo 0x1005
+#define PTP_OC_GetNumObjects 0x1006
+#define PTP_OC_GetObjectHandles 0x1007
+#define PTP_OC_GetObjectInfo 0x1008
+#define PTP_OC_GetObject 0x1009
+#define PTP_OC_GetThumb 0x100A
+#define PTP_OC_DeleteObject 0x100B
+#define PTP_OC_SendObjectInfo 0x100C
+#define PTP_OC_SendObject 0x100D
+#define PTP_OC_InitiateCapture 0x100E
+#define PTP_OC_FormatStore 0x100F
+#define PTP_OC_ResetDevice 0x1010
+#define PTP_OC_SelfTest 0x1011
+#define PTP_OC_SetObjectProtection 0x1012
+#define PTP_OC_PowerDown 0x1013
+#define PTP_OC_GetDevicePropDesc 0x1014
+#define PTP_OC_GetDevicePropValue 0x1015
+#define PTP_OC_SetDevicePropValue 0x1016
+#define PTP_OC_ResetDevicePropValue 0x1017
+#define PTP_OC_TerminateOpenCapture 0x1018
+#define PTP_OC_MoveObject 0x1019
+#define PTP_OC_CopyObject 0x101A
+#define PTP_OC_GetPartialObject 0x101B
+#define PTP_OC_InitiateOpenCapture 0x101C
+
+/* PTP v1.1 operation codes */
+#define PTP_OC_StartEnumHandles 0x101D
+#define PTP_OC_EnumHandles 0x101E
+#define PTP_OC_StopEnumHandles 0x101F
+#define PTP_OC_GetVendorExtensionMaps 0x1020
+#define PTP_OC_GetVendorDeviceInfo 0x1021
+#define PTP_OC_GetResizedImageObject 0x1022
+#define PTP_OC_GetFilesystemManifest 0x1023
+#define PTP_OC_GetStreamInfo 0x1024
+#define PTP_OC_GetStream 0x1025
+
+ /* Microsoft / MTP extension codes */
+#define PTP_OC_GetObjectPropsSupported 0x9801
+#define PTP_OC_GetObjectPropDesc 0x9802
+#define PTP_OC_GetObjectPropValue 0x9803
+#define PTP_OC_SetObjectPropValue 0x9804
+#define PTP_OC_GetObjPropList 0x9805
+#define PTP_OC_SetObjPropList 0x9806
+#define PTP_OC_GetInterdependendPropdesc 0x9807
+#define PTP_OC_SendObjectPropList 0x9808
+#define PTP_OC_GetObjectReferences 0x9810
+#define PTP_OC_SetObjectReferences 0x9811
+#define PTP_OC_UpdateDeviceFirmware 0x9812
+#define PTP_OC_Skip 0x9820
+
+
+/* Response Codes */
+
+/* PTP v1.0 response codes */
+#define PTP_RC_Undefined 0x2000
+#define PTP_RC_OK 0x2001
+#define PTP_RC_GeneralError 0x2002
+#define PTP_RC_SessionNotOpen 0x2003
+#define PTP_RC_InvalidTransactionID 0x2004
+#define PTP_RC_OperationNotSupported 0x2005
+#define PTP_RC_ParameterNotSupported 0x2006
+#define PTP_RC_IncompleteTransfer 0x2007
+#define PTP_RC_InvalidStorageId 0x2008
+#define PTP_RC_InvalidObjectHandle 0x2009
+#define PTP_RC_DevicePropNotSupported 0x200A
+#define PTP_RC_InvalidObjectFormatCode 0x200B
+#define PTP_RC_StoreFull 0x200C
+#define PTP_RC_ObjectWriteProtected 0x200D
+#define PTP_RC_StoreReadOnly 0x200E
+#define PTP_RC_AccessDenied 0x200F
+#define PTP_RC_NoThumbnailPresent 0x2010
+#define PTP_RC_SelfTestFailed 0x2011
+#define PTP_RC_PartialDeletion 0x2012
+#define PTP_RC_StoreNotAvailable 0x2013
+#define PTP_RC_SpecificationByFormatUnsupported 0x2014
+#define PTP_RC_NoValidObjectInfo 0x2015
+#define PTP_RC_InvalidCodeFormat 0x2016
+#define PTP_RC_UnknownVendorCode 0x2017
+#define PTP_RC_CaptureAlreadyTerminated 0x2018
+#define PTP_RC_DeviceBusy 0x2019
+#define PTP_RC_InvalidParentObject 0x201A
+#define PTP_RC_InvalidDevicePropFormat 0x201B
+#define PTP_RC_InvalidDevicePropValue 0x201C
+#define PTP_RC_InvalidParameter 0x201D
+#define PTP_RC_SessionAlreadyOpened 0x201E
+#define PTP_RC_TransactionCanceled 0x201F
+#define PTP_RC_SpecificationOfDestinationUnsupported 0x2020
+/* PTP v1.1 response codes */
+#define PTP_RC_InvalidEnumHandle 0x2021
+#define PTP_RC_NoStreamEnabled 0x2022
+#define PTP_RC_InvalidDataSet 0x2023
+
+/* USB container types */
+
+#define PTP_USB_CONTAINER_UNDEFINED 0x0000
+#define PTP_USB_CONTAINER_COMMAND 0x0001
+#define PTP_USB_CONTAINER_DATA 0x0002
+#define PTP_USB_CONTAINER_RESPONSE 0x0003
+#define PTP_USB_CONTAINER_EVENT 0x0004
+
+/* PTP/IP definitions */
+#define PTPIP_INIT_COMMAND_REQUEST 1
+#define PTPIP_INIT_COMMAND_ACK 2
+#define PTPIP_INIT_EVENT_REQUEST 3
+#define PTPIP_INIT_EVENT_ACK 4
+#define PTPIP_INIT_FAIL 5
+#define PTPIP_CMD_REQUEST 6
+#define PTPIP_CMD_RESPONSE 7
+#define PTPIP_EVENT 8
+#define PTPIP_START_DATA_PACKET 9
+#define PTPIP_DATA_PACKET 10
+#define PTPIP_CANCEL_TRANSACTION 11
+#define PTPIP_END_DATA_PACKET 12
+#define PTPIP_PING 13
+#define PTPIP_PONG 14
+
+/* Transaction data phase description */
+#define PTP_DP_NODATA 0x0000 /* no data phase */
+#define PTP_DP_SENDDATA 0x0001 /* sending data */
+#define PTP_DP_GETDATA 0x0002 /* receiving data */
+#define PTP_DP_DATA_MASK 0x00ff /* data phase mask */
+
+/** @defgroup USBH_MTP_PTP_Exported_Types
+ * @{
+ */
+
+typedef enum
+{
+ PTP_REQ_IDLE = 0,
+ PTP_REQ_SEND = 1,
+ PTP_REQ_WAIT,
+ PTP_REQ_ERROR,
+}
+PTP_RequestStateTypeDef;
+
+typedef enum
+{
+ PTP_IDLE = 0,
+ PTP_OP_REQUEST_STATE,
+ PTP_OP_REQUEST_WAIT_STATE,
+ PTP_DATA_OUT_PHASE_STATE,
+ PTP_DATA_OUT_PHASE_WAIT_STATE,
+ PTP_DATA_IN_PHASE_STATE,
+ PTP_DATA_IN_PHASE_WAIT_STATE,
+ PTP_RESPONSE_STATE,
+ PTP_RESPONSE_WAIT_STATE,
+ PTP_ERROR,
+}
+PTP_ProcessStateTypeDef;
+
+/* PTP request/response/event general PTP container (transport independent) */
+typedef struct
+{
+ uint16_t Code;
+ uint32_t SessionID;
+ uint32_t Transaction_ID;
+ /* params may be of any type of size less or equal to uint32_t */
+ uint32_t Param1;
+ uint32_t Param2;
+ uint32_t Param3;
+ /* events can only have three parameters */
+ uint32_t Param4;
+ uint32_t Param5;
+ /* the number of meaningfull parameters */
+ uint8_t Nparam;
+}
+PTP_ContainerTypedef;
+
+#define PTP_USB_BULK_HS_MAX_PACKET_LEN_WRITE 1024
+#define PTP_USB_BULK_HS_MAX_PACKET_LEN_READ 1024
+#define PTP_USB_BULK_HDR_LEN (2*sizeof(uint32_t)+2*sizeof(uint16_t))
+#define PTP_USB_BULK_PAYLOAD_LEN_WRITE (PTP_USB_BULK_HS_MAX_PACKET_LEN_WRITE-PTP_USB_BULK_HDR_LEN)
+#define PTP_USB_BULK_PAYLOAD_LEN_READ (PTP_USB_BULK_HS_MAX_PACKET_LEN_READ-PTP_USB_BULK_HDR_LEN)
+#define PTP_USB_BULK_REQ_LEN (PTP_USB_BULK_HDR_LEN+5*sizeof(uint32_t))
+#define PTP_USB_BULK_REQ_RESP_MAX_LEN 63
+
+typedef struct
+{
+ uint32_t length;
+ uint16_t type;
+ uint16_t code;
+ uint32_t trans_id;
+ uint32_t param1;
+ uint32_t param2;
+ uint32_t param3;
+ uint32_t param4;
+ uint32_t param5;
+}
+PTP_RespContainerTypedef;
+
+
+typedef struct
+{
+ uint32_t length;
+ uint16_t type;
+ uint16_t code;
+ uint32_t trans_id;
+ uint32_t param1;
+ uint32_t param2;
+ uint32_t param3;
+ uint32_t param4;
+ uint32_t param5;
+}
+PTP_OpContainerTypedef;
+
+typedef struct
+{
+ uint32_t length;
+ uint16_t type;
+ uint16_t code;
+ uint32_t trans_id;
+ union {
+ struct {
+ uint32_t param1;
+ uint32_t param2;
+ uint32_t param3;
+ uint32_t param4;
+ uint32_t param5;
+ } params;
+ uint8_t data[PTP_USB_BULK_PAYLOAD_LEN_READ];
+ }payload;
+}
+PTP_DataContainerTypedef;
+
+/* PTP USB Asynchronous Event Interrupt Data Format */
+typedef struct
+{
+ uint32_t length;
+ uint16_t type;
+ uint16_t code;
+ uint32_t trans_id;
+ uint32_t param1;
+ uint32_t param2;
+ uint32_t param3;
+}
+PTP_EventContainerTypedef;
+
+/* Structure for PTP Transport process */
+typedef struct
+{
+ PTP_ProcessStateTypeDef state;
+ PTP_RequestStateTypeDef req_state;
+ PTP_OpContainerTypedef op_container;
+ PTP_DataContainerTypedef data_container;
+ PTP_RespContainerTypedef resp_container;
+
+ /* ptp transaction ID */
+ uint32_t transaction_id;
+
+ /* ptp session ID */
+ uint32_t session_id;
+
+ /* device flags */
+ uint32_t flags;
+
+ /****** PTP transfer control *******/
+
+ /* Data pointer */
+ uint8_t *data_ptr;
+
+ /* Data length */
+ int32_t data_length;
+
+ /* Data length */
+ uint32_t data_packet;
+
+ /* Data length */
+ uint32_t iteration;
+
+ /* Packet Index */
+ uint32_t data_packet_counter;
+
+ /****** Object transfer control *******/
+
+ /* object pointer */
+ uint8_t *object_ptr;
+
+}
+PTP_HandleTypeDef;
+
+/* DeviceInfo data offset */
+#define PTP_di_StandardVersion 0
+#define PTP_di_VendorExtensionID 2
+#define PTP_di_VendorExtensionVersion 6
+#define PTP_di_VendorExtensionDesc 8
+#define PTP_di_FunctionalMode 8
+#define PTP_di_OperationsSupported 10
+
+/* Max info items size */
+#define PTP_SUPPORTED_OPERATIONS_NBR 100
+#define PTP_SUPPORTED_EVENTS_NBR 100
+#define PTP_SUPPORTED_PROPRIETIES_NBR 100
+#define PTP_CAPTURE_FORMATS_NBR 100
+#define PTP_IMAGE_FORMATS_NBR 100
+#define PTP_MAX_STR_SIZE 255
+/* PTP device info structure */
+typedef struct
+{
+ uint16_t StandardVersion;
+ uint32_t VendorExtensionID;
+ uint16_t VendorExtensionVersion;
+ uint8_t VendorExtensionDesc[PTP_MAX_STR_SIZE];
+ uint16_t FunctionalMode;
+ uint32_t OperationsSupported_len;
+ uint16_t OperationsSupported[PTP_SUPPORTED_OPERATIONS_NBR];
+ uint32_t EventsSupported_len;
+ uint16_t EventsSupported[PTP_SUPPORTED_EVENTS_NBR];
+ uint32_t DevicePropertiesSupported_len;
+ uint16_t DevicePropertiesSupported[PTP_SUPPORTED_PROPRIETIES_NBR];
+ uint32_t CaptureFormats_len;
+ uint16_t CaptureFormats[PTP_CAPTURE_FORMATS_NBR];
+ uint32_t ImageFormats_len;
+ uint16_t ImageFormats[PTP_IMAGE_FORMATS_NBR];
+ uint8_t Manufacturer[PTP_MAX_STR_SIZE];
+ uint8_t Model[PTP_MAX_STR_SIZE];
+ uint8_t DeviceVersion[PTP_MAX_STR_SIZE];
+ uint8_t SerialNumber[PTP_MAX_STR_SIZE];
+}
+PTP_DeviceInfoTypedef;
+
+#define PTP_MAX_STORAGE_UNITS_NBR 5
+/* PTP storageIDs structute (returned by GetStorageIDs) */
+typedef struct
+{
+ uint32_t n;
+ uint32_t Storage [PTP_MAX_STORAGE_UNITS_NBR];
+}
+PTP_StorageIDsTypedef;
+
+/* PTP StorageInfo structure (returned by GetStorageInfo) */
+
+#define PTP_si_StorageType 0
+#define PTP_si_FilesystemType 2
+#define PTP_si_AccessCapability 4
+#define PTP_si_MaxCapability 6
+#define PTP_si_FreeSpaceInBytes 14
+#define PTP_si_FreeSpaceInImages 22
+#define PTP_si_StorageDescription 26
+
+
+/* PTP Storage Types */
+
+#define PTP_ST_Undefined 0x0000
+#define PTP_ST_FixedROM 0x0001
+#define PTP_ST_RemovableROM 0x0002
+#define PTP_ST_FixedRAM 0x0003
+#define PTP_ST_RemovableRAM 0x0004
+
+/* PTP FilesystemType Values */
+
+#define PTP_FST_Undefined 0x0000
+#define PTP_FST_GenericFlat 0x0001
+#define PTP_FST_GenericHierarchical 0x0002
+#define PTP_FST_DCF 0x0003
+
+/* PTP StorageInfo AccessCapability Values */
+
+#define PTP_AC_ReadWrite 0x0000
+#define PTP_AC_ReadOnly 0x0001
+#define PTP_AC_ReadOnly_with_Object_Deletion 0x0002
+
+typedef struct
+{
+ uint16_t StorageType;
+ uint16_t FilesystemType;
+ uint16_t AccessCapability;
+ uint64_t MaxCapability;
+ uint64_t FreeSpaceInBytes;
+ uint32_t FreeSpaceInImages;
+ uint8_t StorageDescription[PTP_MAX_STR_SIZE];
+ uint8_t VolumeLabel[PTP_MAX_STR_SIZE];
+}
+PTP_StorageInfoTypedef;
+
+/* PTP Object Format Codes */
+
+/* ancillary formats */
+#define PTP_OFC_Undefined 0x3000
+#define PTP_OFC_Defined 0x3800
+#define PTP_OFC_Association 0x3001
+#define PTP_OFC_Script 0x3002
+#define PTP_OFC_Executable 0x3003
+#define PTP_OFC_Text 0x3004
+#define PTP_OFC_HTML 0x3005
+#define PTP_OFC_DPOF 0x3006
+#define PTP_OFC_AIFF 0x3007
+#define PTP_OFC_WAV 0x3008
+#define PTP_OFC_MP3 0x3009
+#define PTP_OFC_AVI 0x300A
+#define PTP_OFC_MPEG 0x300B
+#define PTP_OFC_ASF 0x300C
+#define PTP_OFC_QT 0x300D /* guessing */
+/* image formats */
+#define PTP_OFC_EXIF_JPEG 0x3801
+#define PTP_OFC_TIFF_EP 0x3802
+#define PTP_OFC_FlashPix 0x3803
+#define PTP_OFC_BMP 0x3804
+#define PTP_OFC_CIFF 0x3805
+#define PTP_OFC_Undefined_0x3806 0x3806
+#define PTP_OFC_GIF 0x3807
+#define PTP_OFC_JFIF 0x3808
+#define PTP_OFC_PCD 0x3809
+#define PTP_OFC_PICT 0x380A
+#define PTP_OFC_PNG 0x380B
+#define PTP_OFC_Undefined_0x380C 0x380C
+#define PTP_OFC_TIFF 0x380D
+#define PTP_OFC_TIFF_IT 0x380E
+#define PTP_OFC_JP2 0x380F
+#define PTP_OFC_JPX 0x3810
+/* ptp v1.1 has only DNG new */
+#define PTP_OFC_DNG 0x3811
+
+/* MTP extensions */
+#define PTP_OFC_MTP_MediaCard 0xb211
+#define PTP_OFC_MTP_MediaCardGroup 0xb212
+#define PTP_OFC_MTP_Encounter 0xb213
+#define PTP_OFC_MTP_EncounterBox 0xb214
+#define PTP_OFC_MTP_M4A 0xb215
+#define PTP_OFC_MTP_ZUNEUNDEFINED 0xb217 /* Unknown file type */
+#define PTP_OFC_MTP_Firmware 0xb802
+#define PTP_OFC_MTP_WindowsImageFormat 0xb881
+#define PTP_OFC_MTP_UndefinedAudio 0xb900
+#define PTP_OFC_MTP_WMA 0xb901
+#define PTP_OFC_MTP_OGG 0xb902
+#define PTP_OFC_MTP_AAC 0xb903
+#define PTP_OFC_MTP_AudibleCodec 0xb904
+#define PTP_OFC_MTP_FLAC 0xb906
+#define PTP_OFC_MTP_SamsungPlaylist 0xb909
+#define PTP_OFC_MTP_UndefinedVideo 0xb980
+#define PTP_OFC_MTP_WMV 0xb981
+#define PTP_OFC_MTP_MP4 0xb982
+#define PTP_OFC_MTP_MP2 0xb983
+#define PTP_OFC_MTP_3GP 0xb984
+#define PTP_OFC_MTP_UndefinedCollection 0xba00
+#define PTP_OFC_MTP_AbstractMultimediaAlbum 0xba01
+#define PTP_OFC_MTP_AbstractImageAlbum 0xba02
+#define PTP_OFC_MTP_AbstractAudioAlbum 0xba03
+#define PTP_OFC_MTP_AbstractVideoAlbum 0xba04
+#define PTP_OFC_MTP_AbstractAudioVideoPlaylist 0xba05
+#define PTP_OFC_MTP_AbstractContactGroup 0xba06
+#define PTP_OFC_MTP_AbstractMessageFolder 0xba07
+#define PTP_OFC_MTP_AbstractChapteredProduction 0xba08
+#define PTP_OFC_MTP_AbstractAudioPlaylist 0xba09
+#define PTP_OFC_MTP_AbstractVideoPlaylist 0xba0a
+#define PTP_OFC_MTP_AbstractMediacast 0xba0b
+#define PTP_OFC_MTP_WPLPlaylist 0xba10
+#define PTP_OFC_MTP_M3UPlaylist 0xba11
+#define PTP_OFC_MTP_MPLPlaylist 0xba12
+#define PTP_OFC_MTP_ASXPlaylist 0xba13
+#define PTP_OFC_MTP_PLSPlaylist 0xba14
+#define PTP_OFC_MTP_UndefinedDocument 0xba80
+#define PTP_OFC_MTP_AbstractDocument 0xba81
+#define PTP_OFC_MTP_XMLDocument 0xba82
+#define PTP_OFC_MTP_MSWordDocument 0xba83
+#define PTP_OFC_MTP_MHTCompiledHTMLDocument 0xba84
+#define PTP_OFC_MTP_MSExcelSpreadsheetXLS 0xba85
+#define PTP_OFC_MTP_MSPowerpointPresentationPPT 0xba86
+#define PTP_OFC_MTP_UndefinedMessage 0xbb00
+#define PTP_OFC_MTP_AbstractMessage 0xbb01
+#define PTP_OFC_MTP_UndefinedContact 0xbb80
+#define PTP_OFC_MTP_AbstractContact 0xbb81
+#define PTP_OFC_MTP_vCard2 0xbb82
+#define PTP_OFC_MTP_vCard3 0xbb83
+#define PTP_OFC_MTP_UndefinedCalendarItem 0xbe00
+#define PTP_OFC_MTP_AbstractCalendarItem 0xbe01
+#define PTP_OFC_MTP_vCalendar1 0xbe02
+#define PTP_OFC_MTP_vCalendar2 0xbe03
+#define PTP_OFC_MTP_UndefinedWindowsExecutable 0xbe80
+#define PTP_OFC_MTP_MediaCast 0xbe81
+#define PTP_OFC_MTP_Section 0xbe82
+
+/* MTP specific Object Properties */
+#define PTP_OPC_StorageID 0xDC01
+#define PTP_OPC_ObjectFormat 0xDC02
+#define PTP_OPC_ProtectionStatus 0xDC03
+#define PTP_OPC_ObjectSize 0xDC04
+#define PTP_OPC_AssociationType 0xDC05
+#define PTP_OPC_AssociationDesc 0xDC06
+#define PTP_OPC_ObjectFileName 0xDC07
+#define PTP_OPC_DateCreated 0xDC08
+#define PTP_OPC_DateModified 0xDC09
+#define PTP_OPC_Keywords 0xDC0A
+#define PTP_OPC_ParentObject 0xDC0B
+#define PTP_OPC_AllowedFolderContents 0xDC0C
+#define PTP_OPC_Hidden 0xDC0D
+#define PTP_OPC_SystemObject 0xDC0E
+#define PTP_OPC_PersistantUniqueObjectIdentifier 0xDC41
+#define PTP_OPC_SyncID 0xDC42
+#define PTP_OPC_PropertyBag 0xDC43
+#define PTP_OPC_Name 0xDC44
+#define PTP_OPC_CreatedBy 0xDC45
+#define PTP_OPC_Artist 0xDC46
+#define PTP_OPC_DateAuthored 0xDC47
+#define PTP_OPC_Description 0xDC48
+#define PTP_OPC_URLReference 0xDC49
+#define PTP_OPC_LanguageLocale 0xDC4A
+#define PTP_OPC_CopyrightInformation 0xDC4B
+#define PTP_OPC_Source 0xDC4C
+#define PTP_OPC_OriginLocation 0xDC4D
+#define PTP_OPC_DateAdded 0xDC4E
+#define PTP_OPC_NonConsumable 0xDC4F
+#define PTP_OPC_CorruptOrUnplayable 0xDC50
+#define PTP_OPC_ProducerSerialNumber 0xDC51
+#define PTP_OPC_RepresentativeSampleFormat 0xDC81
+#define PTP_OPC_RepresentativeSampleSize 0xDC82
+#define PTP_OPC_RepresentativeSampleHeight 0xDC83
+#define PTP_OPC_RepresentativeSampleWidth 0xDC84
+#define PTP_OPC_RepresentativeSampleDuration 0xDC85
+#define PTP_OPC_RepresentativeSampleData 0xDC86
+#define PTP_OPC_Width 0xDC87
+#define PTP_OPC_Height 0xDC88
+#define PTP_OPC_Duration 0xDC89
+#define PTP_OPC_Rating 0xDC8A
+#define PTP_OPC_Track 0xDC8B
+#define PTP_OPC_Genre 0xDC8C
+#define PTP_OPC_Credits 0xDC8D
+#define PTP_OPC_Lyrics 0xDC8E
+#define PTP_OPC_SubscriptionContentID 0xDC8F
+#define PTP_OPC_ProducedBy 0xDC90
+#define PTP_OPC_UseCount 0xDC91
+#define PTP_OPC_SkipCount 0xDC92
+#define PTP_OPC_LastAccessed 0xDC93
+#define PTP_OPC_ParentalRating 0xDC94
+#define PTP_OPC_MetaGenre 0xDC95
+#define PTP_OPC_Composer 0xDC96
+#define PTP_OPC_EffectiveRating 0xDC97
+#define PTP_OPC_Subtitle 0xDC98
+#define PTP_OPC_OriginalReleaseDate 0xDC99
+#define PTP_OPC_AlbumName 0xDC9A
+#define PTP_OPC_AlbumArtist 0xDC9B
+#define PTP_OPC_Mood 0xDC9C
+#define PTP_OPC_DRMStatus 0xDC9D
+#define PTP_OPC_SubDescription 0xDC9E
+#define PTP_OPC_IsCropped 0xDCD1
+#define PTP_OPC_IsColorCorrected 0xDCD2
+#define PTP_OPC_ImageBitDepth 0xDCD3
+#define PTP_OPC_Fnumber 0xDCD4
+#define PTP_OPC_ExposureTime 0xDCD5
+#define PTP_OPC_ExposureIndex 0xDCD6
+#define PTP_OPC_DisplayName 0xDCE0
+#define PTP_OPC_BodyText 0xDCE1
+#define PTP_OPC_Subject 0xDCE2
+#define PTP_OPC_Priority 0xDCE3
+#define PTP_OPC_GivenName 0xDD00
+#define PTP_OPC_MiddleNames 0xDD01
+#define PTP_OPC_FamilyName 0xDD02
+#define PTP_OPC_Prefix 0xDD03
+#define PTP_OPC_Suffix 0xDD04
+#define PTP_OPC_PhoneticGivenName 0xDD05
+#define PTP_OPC_PhoneticFamilyName 0xDD06
+#define PTP_OPC_EmailPrimary 0xDD07
+#define PTP_OPC_EmailPersonal1 0xDD08
+#define PTP_OPC_EmailPersonal2 0xDD09
+#define PTP_OPC_EmailBusiness1 0xDD0A
+#define PTP_OPC_EmailBusiness2 0xDD0B
+#define PTP_OPC_EmailOthers 0xDD0C
+#define PTP_OPC_PhoneNumberPrimary 0xDD0D
+#define PTP_OPC_PhoneNumberPersonal 0xDD0E
+#define PTP_OPC_PhoneNumberPersonal2 0xDD0F
+#define PTP_OPC_PhoneNumberBusiness 0xDD10
+#define PTP_OPC_PhoneNumberBusiness2 0xDD11
+#define PTP_OPC_PhoneNumberMobile 0xDD12
+#define PTP_OPC_PhoneNumberMobile2 0xDD13
+#define PTP_OPC_FaxNumberPrimary 0xDD14
+#define PTP_OPC_FaxNumberPersonal 0xDD15
+#define PTP_OPC_FaxNumberBusiness 0xDD16
+#define PTP_OPC_PagerNumber 0xDD17
+#define PTP_OPC_PhoneNumberOthers 0xDD18
+#define PTP_OPC_PrimaryWebAddress 0xDD19
+#define PTP_OPC_PersonalWebAddress 0xDD1A
+#define PTP_OPC_BusinessWebAddress 0xDD1B
+#define PTP_OPC_InstantMessengerAddress 0xDD1C
+#define PTP_OPC_InstantMessengerAddress2 0xDD1D
+#define PTP_OPC_InstantMessengerAddress3 0xDD1E
+#define PTP_OPC_PostalAddressPersonalFull 0xDD1F
+#define PTP_OPC_PostalAddressPersonalFullLine1 0xDD20
+#define PTP_OPC_PostalAddressPersonalFullLine2 0xDD21
+#define PTP_OPC_PostalAddressPersonalFullCity 0xDD22
+#define PTP_OPC_PostalAddressPersonalFullRegion 0xDD23
+#define PTP_OPC_PostalAddressPersonalFullPostalCode 0xDD24
+#define PTP_OPC_PostalAddressPersonalFullCountry 0xDD25
+#define PTP_OPC_PostalAddressBusinessFull 0xDD26
+#define PTP_OPC_PostalAddressBusinessLine1 0xDD27
+#define PTP_OPC_PostalAddressBusinessLine2 0xDD28
+#define PTP_OPC_PostalAddressBusinessCity 0xDD29
+#define PTP_OPC_PostalAddressBusinessRegion 0xDD2A
+#define PTP_OPC_PostalAddressBusinessPostalCode 0xDD2B
+#define PTP_OPC_PostalAddressBusinessCountry 0xDD2C
+#define PTP_OPC_PostalAddressOtherFull 0xDD2D
+#define PTP_OPC_PostalAddressOtherLine1 0xDD2E
+#define PTP_OPC_PostalAddressOtherLine2 0xDD2F
+#define PTP_OPC_PostalAddressOtherCity 0xDD30
+#define PTP_OPC_PostalAddressOtherRegion 0xDD31
+#define PTP_OPC_PostalAddressOtherPostalCode 0xDD32
+#define PTP_OPC_PostalAddressOtherCountry 0xDD33
+#define PTP_OPC_OrganizationName 0xDD34
+#define PTP_OPC_PhoneticOrganizationName 0xDD35
+#define PTP_OPC_Role 0xDD36
+#define PTP_OPC_Birthdate 0xDD37
+#define PTP_OPC_MessageTo 0xDD40
+#define PTP_OPC_MessageCC 0xDD41
+#define PTP_OPC_MessageBCC 0xDD42
+#define PTP_OPC_MessageRead 0xDD43
+#define PTP_OPC_MessageReceivedTime 0xDD44
+#define PTP_OPC_MessageSender 0xDD45
+#define PTP_OPC_ActivityBeginTime 0xDD50
+#define PTP_OPC_ActivityEndTime 0xDD51
+#define PTP_OPC_ActivityLocation 0xDD52
+#define PTP_OPC_ActivityRequiredAttendees 0xDD54
+#define PTP_OPC_ActivityOptionalAttendees 0xDD55
+#define PTP_OPC_ActivityResources 0xDD56
+#define PTP_OPC_ActivityAccepted 0xDD57
+#define PTP_OPC_Owner 0xDD5D
+#define PTP_OPC_Editor 0xDD5E
+#define PTP_OPC_Webmaster 0xDD5F
+#define PTP_OPC_URLSource 0xDD60
+#define PTP_OPC_URLDestination 0xDD61
+#define PTP_OPC_TimeBookmark 0xDD62
+#define PTP_OPC_ObjectBookmark 0xDD63
+#define PTP_OPC_ByteBookmark 0xDD64
+#define PTP_OPC_LastBuildDate 0xDD70
+#define PTP_OPC_TimetoLive 0xDD71
+#define PTP_OPC_MediaGUID 0xDD72
+#define PTP_OPC_TotalBitRate 0xDE91
+#define PTP_OPC_BitRateType 0xDE92
+#define PTP_OPC_SampleRate 0xDE93
+#define PTP_OPC_NumberOfChannels 0xDE94
+#define PTP_OPC_AudioBitDepth 0xDE95
+#define PTP_OPC_ScanDepth 0xDE97
+#define PTP_OPC_AudioWAVECodec 0xDE99
+#define PTP_OPC_AudioBitRate 0xDE9A
+#define PTP_OPC_VideoFourCCCodec 0xDE9B
+#define PTP_OPC_VideoBitRate 0xDE9C
+#define PTP_OPC_FramesPerThousandSeconds 0xDE9D
+#define PTP_OPC_KeyFrameDistance 0xDE9E
+#define PTP_OPC_BufferSize 0xDE9F
+#define PTP_OPC_EncodingQuality 0xDEA0
+#define PTP_OPC_EncodingProfile 0xDEA1
+#define PTP_OPC_BuyFlag 0xD901
+
+/* WiFi Provisioning MTP Extension property codes */
+#define PTP_OPC_WirelessConfigurationFile 0xB104
+
+
+/* PTP Association Types */
+#define PTP_AT_Undefined 0x0000
+#define PTP_AT_GenericFolder 0x0001
+#define PTP_AT_Album 0x0002
+#define PTP_AT_TimeSequence 0x0003
+#define PTP_AT_HorizontalPanoramic 0x0004
+#define PTP_AT_VerticalPanoramic 0x0005
+#define PTP_AT_2DPanoramic 0x0006
+#define PTP_AT_AncillaryData 0x0007
+
+#define PTP_MAX_HANDLER_NBR 0x255
+typedef struct
+{
+ uint32_t n;
+ uint32_t Handler[PTP_MAX_HANDLER_NBR];
+}
+PTP_ObjectHandlesTypedef;
+
+
+#define PTP_oi_StorageID 0
+#define PTP_oi_ObjectFormat 4
+#define PTP_oi_ProtectionStatus 6
+#define PTP_oi_ObjectCompressedSize 8
+#define PTP_oi_ThumbFormat 12
+#define PTP_oi_ThumbCompressedSize 14
+#define PTP_oi_ThumbPixWidth 18
+#define PTP_oi_ThumbPixHeight 22
+#define PTP_oi_ImagePixWidth 26
+#define PTP_oi_ImagePixHeight 30
+#define PTP_oi_ImageBitDepth 34
+#define PTP_oi_ParentObject 38
+#define PTP_oi_AssociationType 42
+#define PTP_oi_AssociationDesc 44
+#define PTP_oi_SequenceNumber 48
+#define PTP_oi_filenamelen 52
+#define PTP_oi_Filename 53
+
+typedef struct
+{
+ uint32_t StorageID;
+ uint16_t ObjectFormat;
+ uint16_t ProtectionStatus;
+ /* In the regular objectinfo this is 32bit, but we keep the general object size here
+ that also arrives via other methods and so use 64bit */
+ uint64_t ObjectCompressedSize;
+ uint16_t ThumbFormat;
+ uint32_t ThumbCompressedSize;
+ uint32_t ThumbPixWidth;
+ uint32_t ThumbPixHeight;
+ uint32_t ImagePixWidth;
+ uint32_t ImagePixHeight;
+ uint32_t ImageBitDepth;
+ uint32_t ParentObject;
+ uint16_t AssociationType;
+ uint32_t AssociationDesc;
+ uint32_t SequenceNumber;
+ uint8_t Filename[PTP_MAX_STR_SIZE];
+ uint32_t CaptureDate;
+ uint32_t ModificationDate;
+ uint8_t Keywords[PTP_MAX_STR_SIZE];
+}
+PTP_ObjectInfoTypedef;
+
+/* Object Property Describing Dataset (DevicePropDesc) */
+
+typedef union _PTP_PropertyValueTypedef
+{
+ char str[PTP_MAX_STR_SIZE];
+ uint8_t u8;
+ int8_t i8;
+ uint16_t u16;
+ int16_t i16;
+ uint32_t u32;
+ int32_t i32;
+ uint64_t u64;
+ int64_t i64;
+
+ struct array {
+ uint32_t count;
+ union _PTP_PropertyValueTypedef *v;
+ } a;
+}PTP_PropertyValueTypedef;
+
+typedef struct
+{
+ PTP_PropertyValueTypedef MinimumValue;
+ PTP_PropertyValueTypedef MaximumValue;
+ PTP_PropertyValueTypedef StepSize;
+}
+PTP_PropDescRangeFormTypedef;
+
+/* Property Describing Dataset, Enum Form */
+
+typedef struct
+{
+ uint16_t NumberOfValues;
+ PTP_PropertyValueTypedef SupportedValue[PTP_SUPPORTED_PROPRIETIES_NBR];
+}
+PTP_PropDescEnumFormTypedef;
+
+/* (MTP) Object Property pack/unpack */
+#define PTP_opd_ObjectPropertyCode 0
+#define PTP_opd_DataType 2
+#define PTP_opd_GetSet 4
+#define PTP_opd_FactoryDefaultValue 5
+
+typedef struct
+{
+ uint16_t ObjectPropertyCode;
+ uint16_t DataType;
+ uint8_t GetSet;
+ PTP_PropertyValueTypedef FactoryDefaultValue;
+ uint32_t GroupCode;
+ uint8_t FormFlag;
+ union {
+ PTP_PropDescEnumFormTypedef Enum;
+ PTP_PropDescRangeFormTypedef Range;
+ } FORM;
+}
+PTP_ObjectPropDescTypeDef;
+
+/* Metadata lists for MTP operations */
+typedef struct
+{
+ uint16_t property;
+ uint16_t datatype;
+ uint32_t ObjectHandle;
+ PTP_PropertyValueTypedef propval;
+}
+MTP_PropertiesTypedef;
+
+
+/* Device Property Form Flag */
+
+#define PTP_DPFF_None 0x00
+#define PTP_DPFF_Range 0x01
+#define PTP_DPFF_Enumeration 0x02
+
+/* Object Property Codes used by MTP (first 3 are same as DPFF codes) */
+#define PTP_OPFF_None 0x00
+#define PTP_OPFF_Range 0x01
+#define PTP_OPFF_Enumeration 0x02
+#define PTP_OPFF_DateTime 0x03
+#define PTP_OPFF_FixedLengthArray 0x04
+#define PTP_OPFF_RegularExpression 0x05
+#define PTP_OPFF_ByteArray 0x06
+#define PTP_OPFF_LongString 0xFF
+
+/* Device Property pack/unpack */
+
+#define PTP_dpd_DevicePropertyCode 0
+#define PTP_dpd_DataType 2
+#define PTP_dpd_GetSet 4
+#define PTP_dpd_FactoryDefaultValue 5
+
+/* Device Property Describing Dataset (DevicePropDesc) */
+
+typedef struct
+{
+ uint16_t DevicePropertyCode;
+ uint16_t DataType;
+ uint8_t GetSet;
+ PTP_PropertyValueTypedef FactoryDefaultValue;
+ PTP_PropertyValueTypedef CurrentValue;
+ uint8_t FormFlag;
+ union {
+ PTP_PropDescEnumFormTypedef Enum;
+ PTP_PropDescRangeFormTypedef Range;
+ } FORM;
+}
+PTP_DevicePropDescTypdef;
+
+/* DataType Codes */
+
+#define PTP_DTC_UNDEF 0x0000
+#define PTP_DTC_INT8 0x0001
+#define PTP_DTC_UINT8 0x0002
+#define PTP_DTC_INT16 0x0003
+#define PTP_DTC_UINT16 0x0004
+#define PTP_DTC_INT32 0x0005
+#define PTP_DTC_UINT32 0x0006
+#define PTP_DTC_INT64 0x0007
+#define PTP_DTC_UINT64 0x0008
+#define PTP_DTC_INT128 0x0009
+#define PTP_DTC_UINT128 0x000A
+
+#define PTP_DTC_ARRAY_MASK 0x4000
+
+#define PTP_DTC_AINT8 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT8)
+#define PTP_DTC_AUINT8 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT8)
+#define PTP_DTC_AINT16 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT16)
+#define PTP_DTC_AUINT16 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT16)
+#define PTP_DTC_AINT32 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT32)
+#define PTP_DTC_AUINT32 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT32)
+#define PTP_DTC_AINT64 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT64)
+#define PTP_DTC_AUINT64 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT64)
+#define PTP_DTC_AINT128 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT128)
+#define PTP_DTC_AUINT128 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT128)
+
+#define PTP_DTC_STR 0xFFFF
+
+/* PTP Event Codes */
+
+#define PTP_EC_Undefined 0x4000
+#define PTP_EC_CancelTransaction 0x4001
+#define PTP_EC_ObjectAdded 0x4002
+#define PTP_EC_ObjectRemoved 0x4003
+#define PTP_EC_StoreAdded 0x4004
+#define PTP_EC_StoreRemoved 0x4005
+#define PTP_EC_DevicePropChanged 0x4006
+#define PTP_EC_ObjectInfoChanged 0x4007
+#define PTP_EC_DeviceInfoChanged 0x4008
+#define PTP_EC_RequestObjectTransfer 0x4009
+#define PTP_EC_StoreFull 0x400A
+#define PTP_EC_DeviceReset 0x400B
+#define PTP_EC_StorageInfoChanged 0x400C
+#define PTP_EC_CaptureComplete 0x400D
+#define PTP_EC_UnreportedStatus 0x400E
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_MTP_PTP_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBH_MTP_PTP_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_MTP_PTP_Exported_FunctionsPrototype
+ * @{
+ */
+USBH_StatusTypeDef USBH_PTP_Init(USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_PTP_Process (USBH_HandleTypeDef *phost);
+
+USBH_StatusTypeDef USBH_PTP_SendRequest (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req);
+USBH_StatusTypeDef USBH_PTP_GetResponse (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req);
+
+USBH_StatusTypeDef USBH_PTP_OpenSession (USBH_HandleTypeDef *phost, uint32_t session);
+USBH_StatusTypeDef USBH_PTP_GetDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info);
+USBH_StatusTypeDef USBH_PTP_GetStorageIds (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *storage_ids);
+
+USBH_StatusTypeDef USBH_PTP_GetStorageInfo (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ PTP_StorageInfoTypedef *storage_info);
+
+USBH_StatusTypeDef USBH_PTP_GetNumObjects (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ uint32_t* numobs);
+
+USBH_StatusTypeDef USBH_PTP_GetObjectHandles (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ PTP_ObjectHandlesTypedef* objecthandles);
+
+USBH_StatusTypeDef USBH_PTP_GetObjectInfo (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ PTP_ObjectInfoTypedef* objectinfo);
+
+USBH_StatusTypeDef USBH_PTP_DeleteObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t objectformatcode);
+
+USBH_StatusTypeDef USBH_PTP_GetObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object);
+
+USBH_StatusTypeDef USBH_PTP_GetPartialObject(USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t maxbytes, uint8_t *object,
+ uint32_t *len);
+
+USBH_StatusTypeDef USBH_PTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost,
+ uint16_t ofc,
+ uint32_t *propnum,
+ uint16_t *props);
+
+USBH_StatusTypeDef USBH_PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost,
+ uint16_t opc,
+ uint16_t ofc,
+ PTP_ObjectPropDescTypeDef *opd);
+
+USBH_StatusTypeDef USBH_PTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ MTP_PropertiesTypedef *pprops,
+ uint32_t *nrofprops);
+
+USBH_StatusTypeDef USBH_PTP_SendObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object,
+ uint32_t size);
+
+USBH_StatusTypeDef USBH_PTP_GetDevicePropDesc (USBH_HandleTypeDef *phost,
+ uint16_t propcode,
+ PTP_DevicePropDescTypdef* devicepropertydesc);
+
+/**
+ * @}
+ */
+
+#endif //__USBH_MTP_PTP_H__
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/MTP/Src/usbh_mtp.c b/stmhal/usbhost/Class/MTP/Src/usbh_mtp.c new file mode 100644 index 000000000..d93aa4238 --- /dev/null +++ b/stmhal/usbhost/Class/MTP/Src/usbh_mtp.c @@ -0,0 +1,1065 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the MTP Layer Handlers for USB Host MTP class.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * MTP Class Description
+ * ===================================================================
+ * This module manages the MSC class V1.11 following the "Device Class Definition
+ * for Human Interface Devices (MTP) Version 1.11 Jun 27, 2001".
+ * This driver implements the following aspects of the specification:
+ * - The Boot Interface Subclass
+ * - The Mouse and Keyboard protocols
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_mtp.h"
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_MTP_CLASS
+* @{
+*/
+
+/** @defgroup USBH_MTP_CORE
+* @brief This file includes MTP Layer Handlers for USB Host MTP class.
+* @{
+*/
+
+/** @defgroup USBH_MTP_CORE_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_CORE_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_CORE_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_CORE_Private_Variables
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_CORE_Private_FunctionPrototypes
+* @{
+*/
+
+static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_MTP_Process(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost);
+
+static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost);
+
+static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost);
+
+static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost);
+
+static void MTP_DecodeEvent (USBH_HandleTypeDef *phost) ;
+
+USBH_ClassTypeDef MTP_Class =
+{
+ "MTP",
+ USB_MTP_CLASS,
+ USBH_MTP_InterfaceInit,
+ USBH_MTP_InterfaceDeInit,
+ USBH_MTP_ClassRequest,
+ USBH_MTP_Process,
+ USBH_MTP_SOFProcess,
+ NULL,
+};
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_CORE_Private_Functions
+* @{
+*/
+
+/**
+ * @brief USBH_MTP_InterfaceInit
+ * The function init the MTP class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_OK ;
+ uint8_t interface, endpoint;
+
+ MTP_HandleTypeDef *MTP_Handle;
+
+ interface = USBH_FindInterface(phost,
+ USB_MTP_CLASS,
+ 1,
+ 1);
+
+ if(interface == 0xFF) /* No Valid Interface */
+ {
+ status = USBH_FAIL;
+ USBH_DbgLog ("Cannot Find the interface for Still Image Class.");
+ }
+ else
+ {
+ USBH_SelectInterface (phost, interface);
+
+ endpoint = MTP_FindCtlEndpoint(phost);
+
+ phost->pActiveClass->pData = (MTP_HandleTypeDef *)USBH_malloc (sizeof(MTP_HandleTypeDef));
+ MTP_Handle = phost->pActiveClass->pData;
+
+ if( MTP_Handle == NULL)
+ {
+ status = USBH_FAIL;
+ USBH_DbgLog ("Cannot allocate RAM for MTP Handle");
+ }
+
+ /*Collect the control endpoint address and length*/
+ MTP_Handle->NotificationEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress;
+ MTP_Handle->NotificationEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize;
+ MTP_Handle->NotificationPipe = USBH_AllocPipe(phost, MTP_Handle->NotificationEp);
+ MTP_Handle->events.poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bInterval;
+
+ /* Open pipe for Notification endpoint */
+ USBH_OpenPipe (phost,
+ MTP_Handle->NotificationPipe,
+ MTP_Handle->NotificationEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_INTR,
+ MTP_Handle->NotificationEpSize);
+
+ USBH_LL_SetToggle (phost, MTP_Handle->NotificationPipe, 0);
+
+
+ endpoint = MTP_FindDataInEndpoint(phost);
+
+ /*Collect the control endpoint address and length*/
+ MTP_Handle->DataInEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress;
+ MTP_Handle->DataInEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize;
+ MTP_Handle->DataInPipe = USBH_AllocPipe(phost, MTP_Handle->DataInEp);
+
+ /* Open pipe for DATA IN endpoint */
+ USBH_OpenPipe (phost,
+ MTP_Handle->DataInPipe,
+ MTP_Handle->DataInEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_BULK,
+ MTP_Handle->DataInEpSize);
+
+ USBH_LL_SetToggle (phost, MTP_Handle->DataInPipe, 0);
+
+ endpoint = MTP_FindDataOutEndpoint(phost);
+
+ /*Collect the DATA OUT endpoint address and length*/
+ MTP_Handle->DataOutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress;
+ MTP_Handle->DataOutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize;
+ MTP_Handle->DataOutPipe = USBH_AllocPipe(phost, MTP_Handle->DataOutEp);
+
+ /* Open pipe for DATA OUT endpoint */
+ USBH_OpenPipe (phost,
+ MTP_Handle->DataOutPipe,
+ MTP_Handle->DataOutEp,
+ phost->device.address,
+ phost->device.speed,
+ USB_EP_TYPE_BULK,
+ MTP_Handle->DataOutEpSize);
+
+ USBH_LL_SetToggle (phost, MTP_Handle->DataOutPipe, 0);
+
+
+ MTP_Handle->state = MTP_OPENSESSION;
+ MTP_Handle->is_ready = 0;
+ MTP_Handle->events.state = MTP_EVENTS_INIT;
+ return USBH_PTP_Init(phost);
+
+ }
+ return status;
+}
+
+/**
+ * @brief Find MTP Ctl interface
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface, endpoint;
+
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS)
+ {
+ for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ )
+ {
+ if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&&
+ ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_INTERRUPT) == USBH_EP_INTERRUPT))
+ {
+ return endpoint;
+ }
+ }
+ }
+ }
+
+ return 0xFF; /* Invalid Endpoint */
+}
+
+
+/**
+ * @brief Find MTP DATA OUT interface
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface, endpoint;
+
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS)
+ {
+ for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ )
+ {
+
+ if(((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80) == 0)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&&
+ ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK))
+ {
+ return endpoint;
+ }
+ }
+ }
+ }
+
+ return 0xFF; /* Invalid Endpoint */
+}
+
+/**
+ * @brief Find MTP DATA IN interface
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost)
+{
+ uint8_t interface, endpoint;
+
+ for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ )
+ {
+ if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS)
+ {
+ for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ )
+ {
+
+ if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&&
+ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&&
+ ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK))
+ {
+ return endpoint;
+ }
+ }
+ }
+ }
+
+ return 0xFF; /* Invalid Endpoint */
+}
+
+
+/**
+ * @brief USBH_MTP_InterfaceDeInit
+ * The function DeInit the Pipes used for the MTP class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ if (MTP_Handle->DataOutPipe)
+ {
+ USBH_ClosePipe(phost, MTP_Handle->DataOutPipe);
+ USBH_FreePipe (phost, MTP_Handle->DataOutPipe);
+ MTP_Handle->DataOutPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if (MTP_Handle->DataInPipe)
+ {
+ USBH_ClosePipe(phost, MTP_Handle->DataInPipe);
+ USBH_FreePipe (phost, MTP_Handle->DataInPipe);
+ MTP_Handle->DataInPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if (MTP_Handle->NotificationPipe)
+ {
+ USBH_ClosePipe(phost, MTP_Handle->NotificationPipe);
+ USBH_FreePipe (phost, MTP_Handle->NotificationPipe);
+ MTP_Handle->NotificationPipe = 0; /* Reset the Channel as Free */
+ }
+
+ if(phost->pActiveClass->pData)
+ {
+ USBH_free (phost->pActiveClass->pData);
+ phost->pActiveClass->pData = 0;
+ }
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_MTP_ClassRequest
+ * The function is responsible for handling Standard requests
+ * for MTP class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost)
+{
+ return USBH_OK;;
+}
+
+
+/**
+ * @brief USBH_MTP_Process
+ * The function is for managing state machine for MTP data transfers
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_MTP_Process (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t idx = 0;
+
+ switch(MTP_Handle->state)
+ {
+ case MTP_OPENSESSION:
+
+ status = USBH_PTP_OpenSession (phost, 1); /* Session '0' is not valid */
+
+ if(status == USBH_OK)
+ {
+ USBH_UsrLog("MTP Session #0 Opened");
+ MTP_Handle->state = MTP_GETDEVICEINFO;
+ }
+ break;
+
+ case MTP_GETDEVICEINFO:
+ status = USBH_PTP_GetDeviceInfo (phost, &(MTP_Handle->info.devinfo));
+
+ if(status == USBH_OK)
+ {
+ USBH_DbgLog(">>>>> MTP Device Information");
+ USBH_DbgLog("Standard version : %x", MTP_Handle->info.devinfo.StandardVersion);
+ USBH_DbgLog("Vendor ExtID : %s", (MTP_Handle->info.devinfo.VendorExtensionID == 6)?"MTP": "NOT SUPPORTED");
+ USBH_DbgLog("Functional mode : %s", (MTP_Handle->info.devinfo.FunctionalMode == 0) ? "Standard" : "Vendor");
+ USBH_DbgLog("Number of Supported Operation(s) : %d", MTP_Handle->info.devinfo.OperationsSupported_len);
+ USBH_DbgLog("Number of Supported Events(s) : %d", MTP_Handle->info.devinfo.EventsSupported_len);
+ USBH_DbgLog("Number of Supported Proprieties : %d", MTP_Handle->info.devinfo.DevicePropertiesSupported_len);
+ USBH_DbgLog("Manufacturer : %s", MTP_Handle->info.devinfo.Manufacturer);
+ USBH_DbgLog("Model : %s", MTP_Handle->info.devinfo.Model);
+ USBH_DbgLog("Device version : %s", MTP_Handle->info.devinfo.DeviceVersion);
+ USBH_DbgLog("Serial number : %s", MTP_Handle->info.devinfo.SerialNumber);
+
+ MTP_Handle->state = MTP_GETSTORAGEIDS;
+ }
+ break;
+
+ case MTP_GETSTORAGEIDS:
+ status = USBH_PTP_GetStorageIds (phost, &(MTP_Handle->info.storids));
+
+ if(status == USBH_OK)
+ {
+ USBH_DbgLog("Number of storage ID items : %d", MTP_Handle->info.storids.n);
+ for (idx = 0; idx < MTP_Handle->info.storids.n; idx ++)
+ {
+ USBH_DbgLog("storage#%d ID : %x", idx, MTP_Handle->info.storids.Storage[idx]);
+ }
+
+ MTP_Handle->current_storage_unit = 0;
+ MTP_Handle->state = MTP_GETSTORAGEINFO;
+ }
+ break;
+
+ case MTP_GETSTORAGEINFO:
+ status = USBH_PTP_GetStorageInfo (phost,
+ MTP_Handle->info.storids.Storage[MTP_Handle->current_storage_unit],
+ &((MTP_Handle->info.storinfo)[MTP_Handle->current_storage_unit]));
+
+ if(status == USBH_OK)
+ {
+ USBH_UsrLog("Volume#%lu: %s [%s]", MTP_Handle->current_storage_unit,
+ MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].StorageDescription,
+ MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].VolumeLabel);
+ if(++MTP_Handle->current_storage_unit >= MTP_Handle->info.storids.n)
+ {
+ MTP_Handle->state = MTP_IDLE;
+ MTP_Handle->is_ready = 1;
+ MTP_Handle->current_storage_unit = 0;
+ MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[0];
+
+ USBH_UsrLog( "MTP Class initialized.");
+ USBH_UsrLog("%s is default storage unit", MTP_Handle->info.storinfo[0].StorageDescription);
+ phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
+ }
+ }
+ break;
+
+ case MTP_IDLE:
+ USBH_MTP_Events(phost);
+ default:
+ status = USBH_OK;
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_SOFProcess
+ * The function is for managing SOF callback
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_OK;
+
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_IsReady
+ * Select the storage Unit to be used
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+uint8_t USBH_MTP_IsReady (USBH_HandleTypeDef *phost)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ return (MTP_Handle->is_ready);
+}
+
+/**
+ * @brief USBH_MTP_GetNumStorage
+ * Select the storage Unit to be used
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetNumStorage (USBH_HandleTypeDef *phost, uint8_t *storage_num)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ if(MTP_Handle->is_ready > 0)
+ {
+ *storage_num = MTP_Handle->info.storids.n;
+ status = USBH_OK;
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_SelectStorage
+ * Select the storage Unit to be used
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_SelectStorage (USBH_HandleTypeDef *phost, uint8_t storage_idx)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready))
+ {
+ MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[storage_idx];
+ status = USBH_OK;
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetStorageInfo
+ * Get the storage Unit info
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint8_t storage_idx, MTP_StorageInfoTypedef *info)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready))
+ {
+ *info = MTP_Handle->info.storinfo[storage_idx];
+ status = USBH_OK;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetStorageInfo
+ * Get the storage Unit info
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetNumObjects (USBH_HandleTypeDef *phost,
+ uint32_t storage_idx,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ uint32_t* numobs)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+ if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready))
+ {
+ while ((status = USBH_PTP_GetNumObjects (phost,
+ MTP_Handle->info.storids.Storage[storage_idx],
+ objectformatcode,
+ associationOH,
+ numobs)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+
+/**
+ * @brief USBH_MTP_GetStorageInfo
+ * Get the storage Unit info
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObjectHandles (USBH_HandleTypeDef *phost,
+ uint32_t storage_idx,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ PTP_ObjectHandlesTypedef* objecthandles)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready))
+ {
+ while ((status = USBH_PTP_GetObjectHandles (phost,
+ MTP_Handle->info.storids.Storage[storage_idx],
+ objectformatcode,
+ associationOH,
+ objecthandles)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectInfo
+ * Gets objert info
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObjectInfo (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ PTP_ObjectInfoTypedef* objectinfo)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetObjectInfo (phost, handle, objectinfo)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+/**
+ * @brief USBH_MTP_DeleteObject
+ * Delete an object.
+ * @param phost: Host handle
+ * @param handle : Object Handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_DeleteObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t objectformatcode)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_DeleteObject (phost, handle, objectformatcode)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetObject
+ * Gets object
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetObject (phost, handle, object)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetPartialObject
+ * Gets object
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetPartialObject(USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t maxbytes,
+ uint8_t *object,
+ uint32_t *len)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetPartialObject(phost,
+ handle,
+ offset,
+ maxbytes,
+ object,
+ len)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetObjectPropsSupported
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost,
+ uint16_t ofc,
+ uint32_t *propnum,
+ uint16_t *props)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetObjectPropsSupported (phost,
+ ofc,
+ propnum,
+ props)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetObjectPropDesc
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObjectPropDesc (USBH_HandleTypeDef *phost,
+ uint16_t opc,
+ uint16_t ofc,
+ PTP_ObjectPropDescTypeDef *opd)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetObjectPropDesc (phost,
+ opc,
+ ofc,
+ opd)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_GetObjectPropList
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ MTP_PropertiesTypedef *pprops,
+ uint32_t *nrofprops)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetObjectPropList (phost,
+ handle,
+ pprops,
+ nrofprops)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_MTP_SendObject
+ * Send an object
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_SendObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object,
+ uint32_t size)
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_SendObject (phost, handle, object, size)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+
+ /**
+ * @brief Handle HID Control process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY ;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+
+ switch(MTP_Handle->events.state)
+ {
+ case MTP_EVENTS_INIT:
+ if((phost->Timer & 1) == 0)
+ {
+ MTP_Handle->events.timer = phost->Timer;
+ USBH_InterruptReceiveData(phost,
+ (uint8_t *)&(MTP_Handle->events.container),
+ MTP_Handle->NotificationEpSize,
+ MTP_Handle->NotificationPipe);
+
+
+ MTP_Handle->events.state = MTP_EVENTS_GETDATA ;
+ }
+ break;
+ case MTP_EVENTS_GETDATA:
+ if(USBH_LL_GetURBState(phost , MTP_Handle->NotificationPipe) == USBH_URB_DONE)
+ {
+ MTP_DecodeEvent(phost);
+ }
+
+ if(( phost->Timer - MTP_Handle->events.timer) >= MTP_Handle->events.poll)
+ {
+ MTP_Handle->events.timer = phost->Timer;
+
+ USBH_InterruptReceiveData(phost,
+ (uint8_t *)&(MTP_Handle->events.container),
+ MTP_Handle->NotificationEpSize,
+ MTP_Handle->NotificationPipe);
+
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief MTP_DecodeEvent
+ * Decode device event sent by responder
+ * @param phost: Host handle
+ * @retval None
+ */
+static void MTP_DecodeEvent (USBH_HandleTypeDef *phost)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ uint16_t code;
+ uint32_t param1;
+
+ /* Process the event */
+ code = MTP_Handle->events.container.code;
+ param1 = MTP_Handle->events.container.param1;
+
+ switch(code)
+ {
+ case PTP_EC_Undefined:
+ USBH_DbgLog("EVT: PTP_EC_Undefined in session %u", MTP_Handle->ptp.session_id);
+ break;
+ case PTP_EC_CancelTransaction:
+ USBH_DbgLog("EVT: PTP_EC_CancelTransaction in session %u", MTP_Handle->ptp.session_id);
+ break;
+ case PTP_EC_ObjectAdded:
+ USBH_DbgLog("EVT: PTP_EC_ObjectAdded in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_ObjectRemoved:
+ USBH_DbgLog("EVT: PTP_EC_ObjectRemoved in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_StoreAdded:
+ USBH_DbgLog("EVT: PTP_EC_StoreAdded in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_StoreRemoved:
+ USBH_DbgLog("EVT: PTP_EC_StoreRemoved in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_DevicePropChanged:
+ USBH_DbgLog("EVT: PTP_EC_DevicePropChanged in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_ObjectInfoChanged:
+ USBH_DbgLog("EVT: PTP_EC_ObjectInfoChanged in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_DeviceInfoChanged:
+ USBH_DbgLog("EVT: PTP_EC_DeviceInfoChanged in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_RequestObjectTransfer:
+ USBH_DbgLog("EVT: PTP_EC_RequestObjectTransfer in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_StoreFull:
+ USBH_DbgLog("EVT: PTP_EC_StoreFull in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_DeviceReset:
+ USBH_DbgLog("EVT: PTP_EC_DeviceReset in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_StorageInfoChanged :
+ USBH_DbgLog( "EVT: PTP_EC_StorageInfoChanged in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_CaptureComplete :
+ USBH_DbgLog( "EVT: PTP_EC_CaptureComplete in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ case PTP_EC_UnreportedStatus :
+ USBH_DbgLog( "EVT: PTP_EC_UnreportedStatus in session %u", MTP_Handle->ptp.session_id);
+ break;
+
+ default :
+ USBH_DbgLog( "Received unknown event in session %u", MTP_Handle->ptp.session_id);
+ break;
+ }
+
+ USBH_MTP_EventsCallback(phost, code, param1);
+}
+
+/**
+ * @brief USBH_MTP_GetDevicePropDesc
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_MTP_GetDevicePropDesc (USBH_HandleTypeDef *phost,
+ uint16_t propcode,
+ PTP_DevicePropDescTypdef* devicepropertydesc)
+
+{
+ USBH_StatusTypeDef status = USBH_FAIL;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint32_t timeout = phost->Timer + 5000;
+
+ if(MTP_Handle->is_ready)
+ {
+ while ((status = USBH_PTP_GetDevicePropDesc (phost, propcode, devicepropertydesc)) == USBH_BUSY)
+ {
+ if((phost->Timer > timeout) || (phost->device.is_connected == 0))
+ {
+ return USBH_FAIL;
+ }
+ }
+ }
+ return status;
+}
+/**
+ * @brief The function informs that host has rceived an event
+ * @param pdev: Selected device
+ * @retval None
+ */
+__weak void USBH_MTP_EventsCallback(USBH_HandleTypeDef *phost, uint32_t event, uint32_t param)
+{
+
+}
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbhost/Class/MTP/Src/usbh_mtp_ptp.c b/stmhal/usbhost/Class/MTP/Src/usbh_mtp_ptp.c new file mode 100644 index 000000000..dd5a293e6 --- /dev/null +++ b/stmhal/usbhost/Class/MTP/Src/usbh_mtp_ptp.c @@ -0,0 +1,1769 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp_ptp.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file includes the PTP operations layer
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_mtp_ptp.h"
+#include "usbh_mtp.h"
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_MTP_CLASS
+* @{
+*/
+
+/** @defgroup USBH_MTP_PTP
+* @brief This file includes the mass storage related functions
+* @{
+*/
+
+
+/** @defgroup USBH_MTP_PTP_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_PTP_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_MTP_PTP_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_PTP_Private_Variables
+* @{
+*/
+
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_PTP_Private_FunctionPrototypes
+* @{
+*/
+static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info);
+static void PTP_GetStorageIDs (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *stor_ids);
+static void PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *stor_info);
+static void PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, PTP_ObjectPropDescTypeDef *opd, uint32_t opdlen);
+static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info);
+static void PTP_GetDevicePropValue(USBH_HandleTypeDef *phost,
+ uint32_t *offset,
+ uint32_t total,
+ PTP_PropertyValueTypedef* value,
+ uint16_t datatype);
+
+static uint32_t PTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ MTP_PropertiesTypedef *props,
+ uint32_t len);
+
+
+static void PTP_BufferFullCallback(USBH_HandleTypeDef *phost);
+static void PTP_GetString(uint8_t *str, uint8_t* data, uint16_t *len);
+static uint32_t PTP_GetArray16 (uint16_t *array, uint8_t *data, uint32_t offset);
+static uint32_t PTP_GetArray32 (uint32_t *array, uint8_t *data, uint32_t offset);
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_PTP_Exported_Variables
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_MTP_PTP_Private_Functions
+* @{
+*/
+/**
+ * @brief USBH_PTP_Init
+ * The function Initializes the BOT protocol.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_Init(USBH_HandleTypeDef *phost)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ /* Set state to idle to be ready for operations */
+ MTP_Handle->ptp.state = PTP_IDLE;
+ MTP_Handle->ptp.req_state = PTP_REQ_SEND;
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_PTP_Process
+ * The function handle the BOT protocol.
+ * @param phost: Host handle
+ * @param lun: Logical Unit Number
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_Process (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+ uint32_t len;
+
+ switch (MTP_Handle->ptp.state)
+ {
+ case PTP_IDLE:
+ /*Do Nothing */
+ break;
+
+ case PTP_OP_REQUEST_STATE:
+ USBH_BulkSendData (phost,
+ (uint8_t*)&(MTP_Handle->ptp.op_container),
+ MTP_Handle->ptp.op_container.length,
+ MTP_Handle->DataOutPipe,
+ 1);
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_WAIT_STATE;
+ break;
+
+ case PTP_OP_REQUEST_WAIT_STATE:
+ URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataOutPipe);
+
+ if(URB_Status == USBH_URB_DONE)
+ {
+ if(MTP_Handle->ptp.flags == PTP_DP_NODATA)
+ {
+ MTP_Handle->ptp.state = PTP_RESPONSE_STATE;
+ }
+ else if(MTP_Handle->ptp.flags == PTP_DP_SENDDATA)
+ {
+ MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_STATE;
+ }
+ else if(MTP_Handle->ptp.flags == PTP_DP_GETDATA)
+ {
+ MTP_Handle->ptp.state = PTP_DATA_IN_PHASE_STATE;
+ }
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_NOTREADY)
+ {
+ /* Re-send Request */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MTP_Handle->ptp.state = PTP_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case PTP_DATA_OUT_PHASE_STATE:
+
+ USBH_BulkSendData (phost,
+ MTP_Handle->ptp.data_ptr,
+ MTP_Handle->DataOutEpSize ,
+ MTP_Handle->DataOutPipe,
+ 1);
+
+
+ MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_WAIT_STATE;
+ break;
+
+ case PTP_DATA_OUT_PHASE_WAIT_STATE:
+ URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataOutPipe);
+
+ if(URB_Status == USBH_URB_DONE)
+ {
+ /* Adjudt Data pointer and data length */
+ if(MTP_Handle->ptp.data_length > MTP_Handle->DataOutEpSize)
+ {
+ MTP_Handle->ptp.data_ptr += MTP_Handle->DataOutEpSize;
+ MTP_Handle->ptp.data_length -= MTP_Handle->DataOutEpSize;
+ MTP_Handle->ptp.data_packet += MTP_Handle->DataOutEpSize;
+
+ if(MTP_Handle->ptp.data_packet >= PTP_USB_BULK_PAYLOAD_LEN_READ)
+ {
+ PTP_BufferFullCallback (phost);
+ MTP_Handle->ptp.data_packet = 0;
+ MTP_Handle->ptp.iteration++;
+ }
+
+ }
+ else
+ {
+ MTP_Handle->ptp.data_length = 0;
+ }
+
+ /* More Data To be Sent */
+ if(MTP_Handle->ptp.data_length > 0)
+ {
+ USBH_BulkSendData (phost,
+ MTP_Handle->ptp.data_ptr,
+ MTP_Handle->DataOutEpSize ,
+ MTP_Handle->DataOutPipe,
+ 1);
+ }
+ else
+ {
+ /* If value was 0, and successful transfer, then change the state */
+ MTP_Handle->ptp.state = PTP_RESPONSE_STATE;
+ }
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+
+ else if(URB_Status == USBH_URB_NOTREADY)
+ {
+ /* Re-send same data */
+ MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_STATE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MTP_Handle->ptp.state = PTP_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case PTP_DATA_IN_PHASE_STATE:
+ /* Send first packet */
+ USBH_BulkReceiveData (phost,
+ MTP_Handle->ptp.data_ptr,
+ MTP_Handle->DataInEpSize,
+ MTP_Handle->DataInPipe);
+
+ MTP_Handle->ptp.state = PTP_DATA_IN_PHASE_WAIT_STATE;
+ break;
+
+ case PTP_DATA_IN_PHASE_WAIT_STATE:
+ URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataInPipe);
+
+ if(URB_Status == USBH_URB_DONE)
+ {
+ len = USBH_LL_GetLastXferSize (phost, MTP_Handle->DataInPipe);
+
+ if( MTP_Handle->ptp.data_packet_counter++ == 0)
+ {
+ /* This is the first packet; so retrieve exact data length from payload */
+ MTP_Handle->ptp.data_length = *(uint32_t*)(MTP_Handle->ptp.data_ptr);
+ MTP_Handle->ptp.iteration = 0;
+ }
+
+ if((len >= MTP_Handle->DataInEpSize) && (MTP_Handle->ptp.data_length > 0))
+ {
+ MTP_Handle->ptp.data_ptr += len;
+ MTP_Handle->ptp.data_length -= len;
+ MTP_Handle->ptp.data_packet += len;
+
+ if(MTP_Handle->ptp.data_packet >= PTP_USB_BULK_PAYLOAD_LEN_READ)
+ {
+ PTP_BufferFullCallback (phost);
+ MTP_Handle->ptp.data_packet = 0;
+ MTP_Handle->ptp.iteration++;
+ }
+
+ /* Continue receiving data*/
+ USBH_BulkReceiveData (phost,
+ MTP_Handle->ptp.data_ptr,
+ MTP_Handle->DataInEpSize,
+ MTP_Handle->DataInPipe);
+ }
+ else
+ {
+ MTP_Handle->ptp.data_length -= len;
+ MTP_Handle->ptp.state = PTP_RESPONSE_STATE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MTP_Handle->ptp.state = PTP_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case PTP_RESPONSE_STATE:
+
+ USBH_BulkReceiveData (phost,
+ (uint8_t*)&(MTP_Handle->ptp.resp_container),
+ PTP_USB_BULK_REQ_RESP_MAX_LEN ,
+ MTP_Handle->DataInPipe);
+
+ MTP_Handle->ptp.state = PTP_RESPONSE_WAIT_STATE;
+ break;
+
+ case PTP_RESPONSE_WAIT_STATE:
+ URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataInPipe);
+
+ if(URB_Status == USBH_URB_DONE)
+ {
+ USBH_PTP_GetResponse (phost, &ptp_container);
+
+ if(ptp_container.Code == PTP_RC_OK)
+ {
+ status = USBH_OK;
+ }
+ else
+ {
+ status = USBH_FAIL;
+ }
+ MTP_Handle->ptp.req_state = PTP_REQ_SEND;
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MTP_Handle->ptp.state = PTP_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ break;
+
+ case PTP_ERROR:
+ MTP_Handle->ptp.req_state = PTP_REQ_SEND;
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_OpenSession
+ * Open a new session
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_SendRequest (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req)
+{
+ USBH_StatusTypeDef status = USBH_OK;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ /* Clear PTP Data container*/
+ USBH_memset(&(MTP_Handle->ptp.op_container), 0, sizeof(PTP_OpContainerTypedef));
+
+ /* build appropriate USB container */
+ MTP_Handle->ptp.op_container.length = PTP_USB_BULK_REQ_LEN- (sizeof(uint32_t)*(5-req->Nparam));
+ MTP_Handle->ptp.op_container.type = PTP_USB_CONTAINER_COMMAND;
+ MTP_Handle->ptp.op_container.code = req->Code;
+ MTP_Handle->ptp.op_container.trans_id = req->Transaction_ID;
+ MTP_Handle->ptp.op_container.param1 = req->Param1;
+ MTP_Handle->ptp.op_container.param2 = req->Param2;
+ MTP_Handle->ptp.op_container.param3 = req->Param3;
+ MTP_Handle->ptp.op_container.param4 = req->Param4;
+ MTP_Handle->ptp.op_container.param5 = req->Param5;
+
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_OpenSession
+ * Open a new session
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetResponse (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *resp)
+{
+ USBH_StatusTypeDef status = USBH_OK;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ /* build an appropriate PTPContainer */
+ resp->Code = MTP_Handle->ptp.resp_container.code;
+ resp->SessionID = MTP_Handle->ptp.session_id;
+ resp->Transaction_ID = MTP_Handle->ptp.resp_container.trans_id;
+ resp->Param1 = MTP_Handle->ptp.resp_container.param1;
+ resp->Param2 = MTP_Handle->ptp.resp_container.param2;
+ resp->Param3 = MTP_Handle->ptp.resp_container.param3;
+ resp->Param4 = MTP_Handle->ptp.resp_container.param4;
+ resp->Param5 = MTP_Handle->ptp.resp_container.param5;
+
+ return status;
+}
+
+/**
+ * @brief The function informs user that data buffer is full
+ * @param phost: host handle
+ * @retval None
+ */
+void PTP_BufferFullCallback(USBH_HandleTypeDef *phost)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+
+ switch (MTP_Handle->ptp.data_container.code)
+ {
+ case PTP_OC_GetDeviceInfo:
+ PTP_DecodeDeviceInfo (phost, &(MTP_Handle->info.devinfo));
+ break;
+
+ case PTP_OC_GetPartialObject:
+ case PTP_OC_GetObject:
+
+ /* first packet is in the PTP data payload buffer */
+ if(MTP_Handle->ptp.iteration == 0)
+ {
+ /* copy it to object */
+ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, PTP_USB_BULK_PAYLOAD_LEN_READ);
+
+ /* next packet should be directly copied to object */
+ MTP_Handle->ptp.data_ptr = (MTP_Handle->ptp.object_ptr + PTP_USB_BULK_PAYLOAD_LEN_READ);
+ }
+ break;
+
+ case PTP_OC_SendObject:
+ /* first packet is in the PTP data payload buffer */
+ if(MTP_Handle->ptp.iteration == 0)
+ {
+ /* next packet should be directly copied to object */
+ MTP_Handle->ptp.data_ptr = (MTP_Handle->ptp.object_ptr + PTP_USB_BULK_PAYLOAD_LEN_READ);
+ }
+ break;
+
+ default:
+ break;
+
+
+ }
+}
+
+/**
+ * @brief PTP_GetDeviceInfo
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval None
+ */
+static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ uint32_t totallen;
+ uint16_t len;
+
+ /* Max device info is PTP_USB_BULK_HS_MAX_PACKET_LEN_READ */
+ USBH_DbgLog (" MTP device info size exceeds internal buffer size.\
+ only available data are decoded.");
+
+ if(MTP_Handle->ptp.iteration == 0)
+ {
+ dev_info->StandardVersion = LE16(&data[PTP_di_StandardVersion]);
+ dev_info->VendorExtensionID = LE32(&data[PTP_di_VendorExtensionID]);
+ dev_info->VendorExtensionVersion = LE16(&data[PTP_di_VendorExtensionVersion]);
+ PTP_GetString(dev_info->VendorExtensionDesc, &data[PTP_di_VendorExtensionDesc], &len);
+
+ totallen=len*2+1;
+ dev_info->FunctionalMode = LE16(&data[PTP_di_FunctionalMode+totallen]);
+ dev_info->OperationsSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->OperationsSupported,
+ data,
+ PTP_di_OperationsSupported+totallen);
+
+ totallen=totallen+dev_info->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
+ dev_info->EventsSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->EventsSupported,
+ data,
+ PTP_di_OperationsSupported+totallen);
+
+ totallen=totallen+dev_info->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
+ dev_info->DevicePropertiesSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->DevicePropertiesSupported,
+ data,
+ PTP_di_OperationsSupported+totallen);
+
+ totallen=totallen+dev_info->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
+
+ dev_info->CaptureFormats_len = PTP_GetArray16 ((uint16_t *)&dev_info->CaptureFormats,
+ data,
+ PTP_di_OperationsSupported+totallen);
+
+ totallen=totallen+dev_info->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
+ dev_info->ImageFormats_len = PTP_GetArray16 ((uint16_t *)&dev_info->ImageFormats,
+ data,
+ PTP_di_OperationsSupported+totallen);
+
+ totallen=totallen+dev_info->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
+ PTP_GetString(dev_info->Manufacturer, &data[PTP_di_OperationsSupported+totallen], &len);
+
+ totallen+=len*2+1;
+ PTP_GetString(dev_info->Model, &data[PTP_di_OperationsSupported+totallen], &len);
+
+ totallen+=len*2+1;
+ PTP_GetString(dev_info->DeviceVersion, &data[PTP_di_OperationsSupported+totallen], &len);
+
+ totallen+=len*2+1;
+ PTP_GetString(dev_info->SerialNumber, &data[PTP_di_OperationsSupported+totallen], &len);
+ }
+}
+
+/**
+ * @brief PTP_GetStorageIDs
+ * Gets Storage Ids and fills stor_ids structure.
+ * @param phost: Host handle
+ * @param stor_ids: Storage IDsstructure
+ * @retval None
+ */
+static void PTP_GetStorageIDs (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *stor_ids)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+
+ stor_ids->n = PTP_GetArray32 (stor_ids->Storage, data, 0);
+}
+
+
+/**
+ * @brief PTP_GetStorageInfo
+ * Gets Storage Info and fills stor_info structure.
+ * @param phost: Host handle
+ * @param stor_ids: Storage IDsstructure
+ * @retval None
+ */
+static void PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *stor_info)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+
+ uint16_t len;
+
+ stor_info->StorageType=LE16(&data[PTP_si_StorageType]);
+ stor_info->FilesystemType=LE16(&data[PTP_si_FilesystemType]);
+ stor_info->AccessCapability=LE16(&data[PTP_si_AccessCapability]);
+ stor_info->MaxCapability=LE64(&data[PTP_si_MaxCapability]);
+ stor_info->FreeSpaceInBytes=LE64(&data[PTP_si_FreeSpaceInBytes]);
+ stor_info->FreeSpaceInImages=LE32(&data[PTP_si_FreeSpaceInImages]);
+
+ PTP_GetString(stor_info->StorageDescription, &data[PTP_si_StorageDescription], &len);
+ PTP_GetString(stor_info->VolumeLabel, &data[PTP_si_StorageDescription+len*2+1], &len);
+}
+
+/**
+ * @brief PTP_GetObjectInfo
+ * Gets objectInfo and fills object_info structure.
+ * @param phost: Host handle
+ * @param object_info: object info structure
+ * @retval None
+ */
+static void PTP_GetObjectInfo (USBH_HandleTypeDef *phost, PTP_ObjectInfoTypedef *object_info)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ uint16_t filenamelen;
+
+ object_info->StorageID=LE32(&data[PTP_oi_StorageID]);
+ object_info->ObjectFormat=LE16(&data[PTP_oi_ObjectFormat]);
+ object_info->ProtectionStatus=LE16(&data[PTP_oi_ProtectionStatus]);
+ object_info->ObjectCompressedSize=LE32(&data[PTP_oi_ObjectCompressedSize]);
+
+ /* For Samsung Galaxy */
+ if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0))
+ {
+ data += 4;
+ }
+ object_info->ThumbFormat=LE16(&data[PTP_oi_ThumbFormat]);
+ object_info->ThumbCompressedSize=LE32(&data[PTP_oi_ThumbCompressedSize]);
+ object_info->ThumbPixWidth=LE32(&data[PTP_oi_ThumbPixWidth]);
+ object_info->ThumbPixHeight=LE32(&data[PTP_oi_ThumbPixHeight]);
+ object_info->ImagePixWidth=LE32(&data[PTP_oi_ImagePixWidth]);
+ object_info->ImagePixHeight=LE32(&data[PTP_oi_ImagePixHeight]);
+ object_info->ImageBitDepth=LE32(&data[PTP_oi_ImageBitDepth]);
+ object_info->ParentObject=LE32(&data[PTP_oi_ParentObject]);
+ object_info->AssociationType=LE16(&data[PTP_oi_AssociationType]);
+ object_info->AssociationDesc=LE32(&data[PTP_oi_AssociationDesc]);
+ object_info->SequenceNumber=LE32(&data[PTP_oi_SequenceNumber]);
+ PTP_GetString(object_info->Filename, &data[PTP_oi_filenamelen], &filenamelen);
+}
+
+
+/**
+ * @brief PTP_GetObjectPropDesc
+ * Gets objectInfo and fills object_info structure.
+ * @param phost: Host handle
+ * @param opd: object prop descriptor structure
+ * @retval None
+ */
+static void PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, PTP_ObjectPropDescTypeDef *opd, uint32_t opdlen)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ uint32_t offset = 0, i;
+
+ opd->ObjectPropertyCode=LE16(&data[PTP_opd_ObjectPropertyCode]);
+ opd->DataType=LE16(&data[PTP_opd_DataType]);
+ opd->GetSet=*(uint8_t *)(&data[PTP_opd_GetSet]);
+
+ offset = PTP_opd_FactoryDefaultValue;
+ PTP_GetDevicePropValue (phost, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
+
+ opd->GroupCode=LE32(&data[offset]);
+ offset+=sizeof(uint32_t);
+
+ opd->FormFlag=*(uint8_t *)(&data[offset]);
+ offset+=sizeof(uint8_t);
+
+ switch (opd->FormFlag)
+ {
+ case PTP_OPFF_Range:
+ PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
+ PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
+ PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
+ break;
+
+ case PTP_OPFF_Enumeration:
+
+ opd->FORM.Enum.NumberOfValues = LE16(&data[offset]);
+ offset+=sizeof(uint16_t);
+
+ for (i=0 ; i < opd->FORM.Enum.NumberOfValues ; i++)
+ {
+ PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief PTP_GetDevicePropValue
+ * Gets objectInfo and fills object_info structure.
+ * @param phost: Host handle
+ * @param opd: object prop descriptor structure
+ * @retval None
+ */
+static void PTP_GetDevicePropValue(USBH_HandleTypeDef *phost,
+ uint32_t *offset,
+ uint32_t total,
+ PTP_PropertyValueTypedef* value,
+ uint16_t datatype)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ uint16_t len;
+ switch (datatype)
+ {
+ case PTP_DTC_INT8:
+ value->i8 = *(uint8_t *)&(data[*offset]);
+ *offset += 1;
+ break;
+ case PTP_DTC_UINT8:
+ value->u8 = *(uint8_t *)&(data[*offset]);
+ *offset += 1;
+ break;
+ case PTP_DTC_INT16:
+
+ value->i16 = LE16(&(data[*offset]));
+ *offset += 2;
+ break;
+ case PTP_DTC_UINT16:
+ value->u16 = LE16(&(data[*offset]));
+ *offset += 2;
+ break;
+ case PTP_DTC_INT32:
+ value->i32 = LE32(&(data[*offset]));
+ *offset += 4;
+ break;
+ case PTP_DTC_UINT32:
+ value->u32 = LE32(&(data[*offset]));
+ *offset += 4;
+ break;
+ case PTP_DTC_INT64:
+ value->i64 = LE64(&(data[*offset]));
+ *offset += 8;
+ break;
+ case PTP_DTC_UINT64:
+ value->u64 = LE64(&(data[*offset]));
+ *offset += 8;
+ break;
+
+ case PTP_DTC_UINT128:
+ *offset += 16;
+ break;
+ case PTP_DTC_INT128:
+ *offset += 16;
+ break;
+
+ case PTP_DTC_STR:
+
+ PTP_GetString((uint8_t *)value->str, (uint8_t *)&(data[*offset]), &len);
+ *offset += len*2+1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief PTP_GetDevicePropValue
+ * Gets objectInfo and fills object_info structure.
+ * @param phost: Host handle
+ * @param opd: object prop descriptor structure
+ * @retval None
+ */
+static uint32_t PTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ MTP_PropertiesTypedef *props,
+ uint32_t len)
+{
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ uint32_t prop_count;
+ uint32_t offset = 0, i;
+
+ prop_count = LE32(data);
+
+
+ if (prop_count == 0)
+ {
+ return 0;
+ }
+
+ data += sizeof(uint32_t);
+ len -= sizeof(uint32_t);
+
+ for (i = 0; i < prop_count; i++)
+ {
+ if (len <= 0)
+ {
+ return 0;
+ }
+
+ props[i].ObjectHandle = LE32(data);
+ data += sizeof(uint32_t);
+ len -= sizeof(uint32_t);
+
+ props[i].property = LE16(data);
+ data += sizeof(uint16_t);
+ len -= sizeof(uint16_t);
+
+ props[i].datatype = LE16(data);
+ data += sizeof(uint16_t);
+ len -= sizeof(uint16_t);
+
+ offset = 0;
+
+ PTP_GetDevicePropValue(phost, &offset, len, &props[i].propval, props[i].datatype);
+
+ data += offset;
+ len -= offset;
+ }
+
+ return prop_count;
+}
+
+/**
+ * @brief PTP_GetString
+ * Gets SCII String from.
+ * @param str: ascii string
+ * @param data: Device info structure
+ * @retval None
+ */
+static void PTP_GetString (uint8_t *str, uint8_t* data, uint16_t *len)
+{
+ uint16_t strlength;
+ uint16_t idx;
+
+ *len = data[0];
+ strlength = 2 * data[0];
+ data ++; /* Adjust the offset ignoring the String Len */
+
+ for (idx = 0; idx < strlength; idx+=2 )
+ {
+ /* Copy Only the string and ignore the UNICODE ID, hence add the src */
+ *str = data[idx];
+ str++;
+ }
+ *str = 0; /* mark end of string */
+}
+
+/**
+ * @brief PTP_GetString
+ * Gets SCII String from.
+ * @param str: ascii string
+ * @param data: Device info structure
+ * @retval None
+ */
+
+static uint32_t PTP_GetArray16 (uint16_t *array, uint8_t *data, uint32_t offset)
+{
+ uint32_t size, idx = 0;
+
+ size=LE32(&data[offset]);
+ while (size > idx)
+ {
+ array[idx] = LE16(&data[offset+(sizeof(uint16_t)*(idx+2))]);
+ idx++;
+ }
+ return size;
+}
+
+/**
+ * @brief PTP_GetString
+ * Gets SCII String from.
+ * @param str: ascii string
+ * @param data: Device info structure
+ * @retval None
+ */
+
+static uint32_t PTP_GetArray32 (uint32_t *array, uint8_t *data, uint32_t offset)
+{
+ uint32_t size, idx = 0;
+
+ size=LE32(&data[offset]);
+ while (size > idx)
+ {
+ array[idx] = LE32(&data[offset+(sizeof(uint32_t)*(idx+1))]);
+ idx++;
+ }
+ return size;
+}
+
+/*******************************************************************************
+
+ PTP Requests
+
+*******************************************************************************/
+/**
+ * @brief USBH_PTP_OpenSession
+ * Open a new session
+ * @param phost: Host handle
+ * @param session: Session ID (MUST BE > 0)
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_OpenSession (USBH_HandleTypeDef *phost, uint32_t session)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Init session params */
+ MTP_Handle->ptp.transaction_id = 0x00000000;
+ MTP_Handle->ptp.session_id = session;
+ MTP_Handle->ptp.flags = PTP_DP_NODATA;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_OpenSession;
+ ptp_container.SessionID = session;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = session;
+ ptp_container.Nparam = 1;
+
+ /* convert request packet inti USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetDevicePropDesc
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetDevicePropDesc (USBH_HandleTypeDef *phost,
+ uint16_t propcode,
+ PTP_DevicePropDescTypdef* devicepropertydesc)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+ uint8_t *data = MTP_Handle->ptp.data_container.payload.data;
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetDevicePropDesc;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = propcode;
+ ptp_container.Nparam = 1;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ devicepropertydesc->DevicePropertyCode = LE16(&data[PTP_dpd_DevicePropertyCode]);
+ devicepropertydesc->DataType = LE16(&data[PTP_dpd_DataType]);
+ devicepropertydesc->GetSet = *(uint8_t *)(&data[PTP_dpd_GetSet]);
+ devicepropertydesc->FormFlag = PTP_DPFF_None;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+/**
+ * @brief USBH_PTP_GetDeviceInfo
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetDeviceInfo;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Nparam = 0;
+
+ /* convert request packet inti USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_DecodeDeviceInfo (phost, dev_info);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetStorageIds
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetStorageIds (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *storage_ids)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetStorageIDs;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Nparam = 0;
+
+ /* convert request packet inti USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_GetStorageIDs (phost, storage_ids);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetDeviceInfo
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *storage_info)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetStorageInfo;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = storage_id;
+ ptp_container.Nparam = 1;
+
+ /* convert request packet inti USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_GetStorageInfo (phost, storage_id, storage_info);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetNumObjects
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetNumObjects (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ uint32_t* numobs)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_NODATA;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetNumObjects;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = storage_id;
+ ptp_container.Param2 = objectformatcode;
+ ptp_container.Param3 = associationOH;
+ ptp_container.Nparam = 3;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ *numobs = MTP_Handle->ptp.resp_container.param1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectHandles
+ * Gets device info dataset and fills deviceinfo structure.
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObjectHandles (USBH_HandleTypeDef *phost,
+ uint32_t storage_id,
+ uint32_t objectformatcode,
+ uint32_t associationOH,
+ PTP_ObjectHandlesTypedef* objecthandles)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObjectHandles;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = storage_id;
+ ptp_container.Param2 = objectformatcode;
+ ptp_container.Param3 = associationOH;
+ ptp_container.Nparam = 3;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ objecthandles->n = PTP_GetArray32 (objecthandles->Handler,
+ MTP_Handle->ptp.data_container.payload.data,
+ 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectInfo
+ * Gets objert info
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObjectInfo (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ PTP_ObjectInfoTypedef* object_info)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObjectInfo;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = handle;
+ ptp_container.Nparam = 1;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_GetObjectInfo (phost, object_info);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_DeleteObject
+ * Delete an object.
+ * @param phost: Host handle
+ * @param handle : Object Handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_DeleteObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t objectformatcode)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_NODATA;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_DeleteObject;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = handle;
+ ptp_container.Param2 = objectformatcode;
+ ptp_container.Nparam = 2;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObject
+ * Gets object
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* set object control params */
+ MTP_Handle->ptp.object_ptr = object;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObject;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = handle;
+ ptp_container.Nparam = 1;
+
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ /* first packet is in the PTP data payload buffer */
+ if(MTP_Handle->ptp.iteration == 0)
+ {
+ /* copy it to object */
+ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, PTP_USB_BULK_PAYLOAD_LEN_READ);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetPartialObject
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetPartialObject(USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t maxbytes,
+ uint8_t *object,
+ uint32_t *len)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* set object control params */
+ MTP_Handle->ptp.object_ptr = object;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetPartialObject;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = handle;
+ ptp_container.Param2 = offset;
+ ptp_container.Param3 = maxbytes;
+ ptp_container.Nparam = 3;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ *len = MTP_Handle->ptp.resp_container.param1;
+ /* first packet is in the PTP data payload buffer */
+ if(MTP_Handle->ptp.iteration == 0)
+ {
+ /* copy it to object */
+ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, *len);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectPropsSupported
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost,
+ uint16_t ofc,
+ uint32_t *propnum,
+ uint16_t *props)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObjectPropsSupported;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = ofc;
+ ptp_container.Nparam = 1;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ *propnum = PTP_GetArray16 (props, MTP_Handle->ptp.data_container.payload.data, 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectPropDesc
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost,
+ uint16_t opc,
+ uint16_t ofc,
+ PTP_ObjectPropDescTypeDef *opd)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObjectPropDesc;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = opc;
+ ptp_container.Param2 = ofc;
+ ptp_container.Nparam = 2;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_GetObjectPropDesc(phost, opd, MTP_Handle->ptp.data_length);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_GetObjectPropList
+ * Gets object partially
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_GetObjectPropList (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ MTP_PropertiesTypedef *pprops,
+ uint32_t *nrofprops)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_GETDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_length = 0;
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+
+ /* copy first packet of the object into data container */
+ USBH_memcpy(MTP_Handle->ptp.data_container.payload.data, MTP_Handle->ptp.object_ptr, PTP_USB_BULK_PAYLOAD_LEN_READ);
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_GetObjPropList;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Param1 = handle;
+ ptp_container.Param2 = 0x00000000U; /* 0x00000000U should be "all formats" */
+ ptp_container.Param3 = 0xFFFFFFFFU; /* 0xFFFFFFFFU should be "all properties" */
+ ptp_container.Param4 = 0x00000000U;
+ ptp_container.Param5 = 0xFFFFFFFFU; /* Return full tree below the Param1 handle */
+ ptp_container.Nparam = 5;
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+
+ if(status == USBH_OK)
+ {
+ PTP_GetObjectPropList (phost, pprops, MTP_Handle->ptp.data_length);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_PTP_SendObject
+ * Send an object
+ * @param phost: Host handle
+ * @param dev_info: Device info structure
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_PTP_SendObject (USBH_HandleTypeDef *phost,
+ uint32_t handle,
+ uint8_t *object,
+ uint32_t size)
+{
+ USBH_StatusTypeDef status = USBH_BUSY;
+ MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData;
+ PTP_ContainerTypedef ptp_container;
+
+ switch(MTP_Handle->ptp.req_state)
+ {
+ case PTP_REQ_SEND:
+
+ /* Set operation request type */
+ MTP_Handle->ptp.flags = PTP_DP_SENDDATA;
+ MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container);
+ MTP_Handle->ptp.data_packet_counter = 0;
+ MTP_Handle->ptp.data_packet = 0;
+ MTP_Handle->ptp.iteration = 0;
+
+ /* set object control params */
+ MTP_Handle->ptp.object_ptr = object;
+ MTP_Handle->ptp.data_length = size;
+
+ /* Fill operation request params */
+ ptp_container.Code = PTP_OC_SendObject;
+ ptp_container.SessionID = MTP_Handle->ptp.session_id;
+ ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++;
+ ptp_container.Nparam = 0;
+
+
+ /* convert request packet into USB raw packet*/
+ USBH_PTP_SendRequest (phost, &ptp_container);
+
+ /* Setup State machine and start transfer */
+ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE;
+ MTP_Handle->ptp.req_state = PTP_REQ_WAIT;
+ status = USBH_BUSY;
+ break;
+
+ case PTP_REQ_WAIT:
+ status = USBH_PTP_Process(phost);
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+
diff --git a/stmhal/usbhost/Class/Template/Inc/usbh_template.h b/stmhal/usbhost/Class/Template/Inc/usbh_template.h new file mode 100644 index 000000000..728a36c86 --- /dev/null +++ b/stmhal/usbhost/Class/Template/Inc/usbh_template.h @@ -0,0 +1,122 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp.h
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file contains all the prototypes for the usbh_template.c
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive ----------------------------------------------*/
+#ifndef __USBH_TEMPLATE_CORE_H
+#define __USBH_TEMPLATE_CORE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_TEMPLATE_CLASS
+* @{
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE
+* @brief This file is the Header file for USBH_TEMPLATE_CORE.c
+* @{
+*/
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USBH_TEMPLATE_CORE_Exported_Types
+* @{
+*/
+
+/* States for TEMPLATE State Machine */
+
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE_Exported_Defines
+* @{
+*/
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE_Exported_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE_Exported_Variables
+* @{
+*/
+extern USBH_ClassTypeDef TEMPLATE_Class;
+#define USBH_TEMPLATE_CLASS &TEMPLATE_Class
+
+/**
+* @}
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE_Exported_FunctionsPrototype
+* @{
+*/
+USBH_StatusTypeDef USBH_TEMPLATE_IOProcess (USBH_HandleTypeDef *phost);
+USBH_StatusTypeDef USBH_TEMPLATE_Init (USBH_HandleTypeDef *phost);
+/**
+* @}
+*/
+
+
+#endif /* __USBH_TEMPLATE_CORE_H */
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbhost/Class/Template/Src/usbh_template.c b/stmhal/usbhost/Class/Template/Src/usbh_template.c new file mode 100644 index 000000000..2ea14a89e --- /dev/null +++ b/stmhal/usbhost/Class/Template/Src/usbh_template.c @@ -0,0 +1,240 @@ +/**
+ ******************************************************************************
+ * @file usbh_mtp.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file is the MTP Layer Handlers for USB Host MTP class.
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbh_template.h"
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_CLASS
+* @{
+*/
+
+/** @addtogroup USBH_TEMPLATE_CLASS
+* @{
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE
+* @brief This file includes TEMPLATE Layer Handlers for USB Host TEMPLATE class.
+* @{
+*/
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_Variables
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_FunctionPrototypes
+* @{
+*/
+
+static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceDeInit (USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_TEMPLATE_Process(USBH_HandleTypeDef *phost);
+
+static USBH_StatusTypeDef USBH_TEMPLATE_ClassRequest (USBH_HandleTypeDef *phost);
+
+
+USBH_ClassTypeDef TEMPLATE_Class =
+{
+ "TEMPLATE",
+ USB_TEMPLATE_CLASS,
+ USBH_TEMPLATE_InterfaceInit,
+ USBH_TEMPLATE_InterfaceDeInit,
+ USBH_TEMPLATE_ClassRequest,
+ USBH_TEMPLATE_Process
+};
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_TEMPLATE_CORE_Private_Functions
+* @{
+*/
+
+/**
+ * @brief USBH_TEMPLATE_InterfaceInit
+ * The function init the TEMPLATE class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceInit (USBH_HandleTypeDef *phost)
+{
+
+ return USBH_OK;
+}
+
+
+
+/**
+ * @brief USBH_TEMPLATE_InterfaceDeInit
+ * The function DeInit the Pipes used for the TEMPLATE class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_TEMPLATE_InterfaceDeInit (USBH_HandleTypeDef *phost)
+{
+
+ return USBH_OK;
+}
+
+/**
+ * @brief USBH_TEMPLATE_ClassRequest
+ * The function is responsible for handling Standard requests
+ * for TEMPLATE class.
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_TEMPLATE_ClassRequest (USBH_HandleTypeDef *phost)
+{
+
+ return USBH_OK;
+}
+
+
+/**
+ * @brief USBH_TEMPLATE_Process
+ * The function is for managing state machine for TEMPLATE data transfers
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_TEMPLATE_Process (USBH_HandleTypeDef *phost)
+{
+
+ return USBH_OK;
+}
+
+
+/**
+ * @brief USBH_TEMPLATE_Init
+ * The function Initialize the TEMPLATE function
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_TEMPLATE_Init (USBH_HandleTypeDef *phost)
+{
+ USBH_StatusTypeDef Status = USBH_BUSY;
+#if (USBH_USE_OS == 1)
+ osEvent event;
+
+ event = osMessageGet( phost->class_ready_event, osWaitForever );
+
+ if( event.status == osEventMessage )
+ {
+ if(event.value.v == USBH_CLASS_EVENT)
+ {
+#else
+
+ while ((Status == USBH_BUSY) || (Status == USBH_FAIL))
+ {
+ /* Host background process */
+ USBH_Process(phost);
+ if(phost->gState == HOST_CLASS)
+ {
+#endif
+ Status = USBH_OK;
+ }
+ }
+ return Status;
+}
+
+/**
+ * @brief USBH_TEMPLATE_IOProcess
+ * TEMPLATE TEMPLATE process
+ * @param phost: Host handle
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_TEMPLATE_IOProcess (USBH_HandleTypeDef *phost)
+{
+ if (phost->device.is_connected == 1)
+ {
+ if(phost->gState == HOST_CLASS)
+ {
+ USBH_TEMPLATE_Process(phost);
+ }
+ }
+
+ return USBH_OK;
+}
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
