From dd38d907244bc0e483c3d760f2ba464a394ec229 Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Tue, 11 Mar 2014 23:55:41 -0700 Subject: Initial checkin with STM HAL This compiles and links, but hasn't been tested on a board yet and even if it was run, it doesn't currently do anything. --- stmhal/usbhost/Class/AUDIO/Inc/usbh_audio.h | 581 ++++++ stmhal/usbhost/Class/AUDIO/Src/usbh_audio.c | 1994 +++++++++++++++++++++ stmhal/usbhost/Class/CDC/Inc/usbh_cdc.h | 449 +++++ stmhal/usbhost/Class/CDC/Src/usbh_cdc.c | 755 ++++++++ stmhal/usbhost/Class/HID/Inc/usbh_hid.h | 341 ++++ stmhal/usbhost/Class/HID/Inc/usbh_hid_keybd.h | 318 ++++ stmhal/usbhost/Class/HID/Inc/usbh_hid_mouse.h | 118 ++ stmhal/usbhost/Class/HID/Inc/usbh_hid_parser.h | 96 + stmhal/usbhost/Class/HID/Inc/usbh_hid_usage.h | 191 ++ stmhal/usbhost/Class/HID/Src/usbh_hid.c | 800 +++++++++ stmhal/usbhost/Class/HID/Src/usbh_hid_keybd.c | 418 +++++ stmhal/usbhost/Class/HID/Src/usbh_hid_mouse.c | 267 +++ stmhal/usbhost/Class/HID/Src/usbh_hid_parser.c | 235 +++ stmhal/usbhost/Class/MSC/Inc/usbh_msc.h | 222 +++ stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h | 233 +++ stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h | 218 +++ stmhal/usbhost/Class/MSC/Src/usbh_msc.c | 795 ++++++++ stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c | 633 +++++++ stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c | 458 +++++ stmhal/usbhost/Class/MTP/Inc/usbh_mtp.h | 263 +++ stmhal/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h | 1038 +++++++++++ stmhal/usbhost/Class/MTP/Src/usbh_mtp.c | 1065 +++++++++++ stmhal/usbhost/Class/MTP/Src/usbh_mtp_ptp.c | 1769 ++++++++++++++++++ stmhal/usbhost/Class/Template/Inc/usbh_template.h | 122 ++ stmhal/usbhost/Class/Template/Src/usbh_template.c | 240 +++ 25 files changed, 13619 insertions(+) create mode 100644 stmhal/usbhost/Class/AUDIO/Inc/usbh_audio.h create mode 100644 stmhal/usbhost/Class/AUDIO/Src/usbh_audio.c create mode 100644 stmhal/usbhost/Class/CDC/Inc/usbh_cdc.h create mode 100644 stmhal/usbhost/Class/CDC/Src/usbh_cdc.c create mode 100644 stmhal/usbhost/Class/HID/Inc/usbh_hid.h create mode 100644 stmhal/usbhost/Class/HID/Inc/usbh_hid_keybd.h create mode 100644 stmhal/usbhost/Class/HID/Inc/usbh_hid_mouse.h create mode 100644 stmhal/usbhost/Class/HID/Inc/usbh_hid_parser.h create mode 100644 stmhal/usbhost/Class/HID/Inc/usbh_hid_usage.h create mode 100644 stmhal/usbhost/Class/HID/Src/usbh_hid.c create mode 100644 stmhal/usbhost/Class/HID/Src/usbh_hid_keybd.c create mode 100644 stmhal/usbhost/Class/HID/Src/usbh_hid_mouse.c create mode 100644 stmhal/usbhost/Class/HID/Src/usbh_hid_parser.c create mode 100644 stmhal/usbhost/Class/MSC/Inc/usbh_msc.h create mode 100644 stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h create mode 100644 stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h create mode 100644 stmhal/usbhost/Class/MSC/Src/usbh_msc.c create mode 100644 stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c create mode 100644 stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c create mode 100644 stmhal/usbhost/Class/MTP/Inc/usbh_mtp.h create mode 100644 stmhal/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h create mode 100644 stmhal/usbhost/Class/MTP/Src/usbh_mtp.c create mode 100644 stmhal/usbhost/Class/MTP/Src/usbh_mtp_ptp.c create mode 100644 stmhal/usbhost/Class/Template/Inc/usbh_template.h create mode 100644 stmhal/usbhost/Class/Template/Src/usbh_template.c (limited to 'stmhal/usbhost/Class') 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +#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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +#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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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<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<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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

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

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_mtp_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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* 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 + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_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****/ -- cgit v1.2.3