diff --git a/Downstream/.cproject b/Downstream/.cproject new file mode 100644 index 0000000..3c70d1b --- /dev/null +++ b/Downstream/.cproject @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Downstream/.gitignore b/Downstream/.gitignore new file mode 100644 index 0000000..ac01e66 --- /dev/null +++ b/Downstream/.gitignore @@ -0,0 +1,2 @@ +/Debug/ +/Release/ diff --git a/Downstream/.project b/Downstream/.project new file mode 100644 index 0000000..d053b40 --- /dev/null +++ b/Downstream/.project @@ -0,0 +1,26 @@ + + + Downstream + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/Downstream/.settings/language.settings.xml b/Downstream/.settings/language.settings.xml new file mode 100644 index 0000000..855a758 --- /dev/null +++ b/Downstream/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Downstream/.settings/org.eclipse.cdt.codan.core.prefs b/Downstream/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..ff135cf --- /dev/null +++ b/Downstream/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,71 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} diff --git a/Downstream/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/Downstream/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 0000000..3c47024 --- /dev/null +++ b/Downstream/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,21 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/CPATH/delimiter=\: +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/CPATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/C_INCLUDE_PATH/delimiter=\: +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/append=true +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/appendContributed=true +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/CPATH/delimiter=\: +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/CPATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/C_INCLUDE_PATH/delimiter=\: +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/append=true +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/appendContributed=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/LIBRARY_PATH/delimiter=\: +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/append=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800/appendContributed=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/LIBRARY_PATH/delimiter=\: +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/append=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207/appendContributed=true diff --git a/Downstream/Downstream Debug OCD STLink.launch b/Downstream/Downstream Debug OCD STLink.launch new file mode 100644 index 0000000..4c08dde --- /dev/null +++ b/Downstream/Downstream Debug OCD STLink.launch @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Downstream/Downstream Debug.launch b/Downstream/Downstream Debug.launch new file mode 100644 index 0000000..13d08c4 --- /dev/null +++ b/Downstream/Downstream Debug.launch @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Downstream/Downstream Release.launch b/Downstream/Downstream Release.launch new file mode 100644 index 0000000..7b86390 --- /dev/null +++ b/Downstream/Downstream Release.launch @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Downstream/Inc/board_config.h b/Downstream/Inc/board_config.h new file mode 100644 index 0000000..cb27120 --- /dev/null +++ b/Downstream/Inc/board_config.h @@ -0,0 +1,61 @@ +/* + * board_config.h + * + * Created on: 25/03/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#ifndef INC_BOARD_CONFIG_H_ +#define INC_BOARD_CONFIG_H_ + + +#define BSRR_SHIFT_HIGH 0 +#define BSRR_SHIFT_LOW 16 + +#define PA_JTMS GPIO_PIN_13 +#define PA_JTCK GPIO_PIN_14 +#define PA_JTDI GPIO_PIN_15 +#define PB_JTDO GPIO_PIN_3 +#define PB_NJTRST GPIO_PIN_4 + +#define FAULT_LED_PIN GPIO_PIN_13 +#define FAULT_LED_PORT GPIOC +#define FAULT_LED_ON (FAULT_LED_PORT->BSRR = (FAULT_LED_PIN << BSRR_SHIFT_LOW)) //Fault LED is active-low +#define FAULT_LED_OFF (FAULT_LED_PORT->BSRR = (FAULT_LED_PIN << BSRR_SHIFT_HIGH)) + +#define H405_FAULT_LED_PIN GPIO_PIN_12 //Fault LED on Olimex H405 board +#define H405_FAULT_LED_ON (FAULT_LED_PORT->BSRR = (H405_FAULT_LED_PIN << BSRR_SHIFT_LOW)) + +#define INT_ACTIVE_PIN GPIO_PIN_2 //Temporary indicator of SPI (or whatever) activity +#define INT_ACTIVE_PORT GPIOA +#define INT_ACTIVE_ON INT_ACTIVE_PORT->BSRR = (INT_ACTIVE_PIN << BSRR_SHIFT_HIGH) +#define INT_ACTIVE_OFF INT_ACTIVE_PORT->BSRR = (INT_ACTIVE_PIN << BSRR_SHIFT_LOW) + +//#define SPI1_NSS_PIN GPIO_PIN_4 +//#define SPI1_NSS_PORT GPIOA + +#define UPSTREAM_TX_REQUEST_PIN GPIO_PIN_3 +#define UPSTREAM_TX_REQUEST_PORT GPIOA +#define UPSTREAM_TX_REQUEST_ASSERT (UPSTREAM_TX_REQUEST_PORT->BSRR = (UPSTREAM_TX_REQUEST_PIN << BSRR_SHIFT_LOW)) +#define UPSTREAM_TX_REQUEST_DEASSERT (UPSTREAM_TX_REQUEST_PORT->BSRR = (UPSTREAM_TX_REQUEST_PIN << BSRR_SHIFT_HIGH)) + +#define DBGMCU_IDCODE_DEV_ID_405_407_415_417 0x413 +#define DBGMCU_IDCODE_DEV_ID_401xB_xC 0x423 + +#define BOARD_REV_PIN_MASK 0xE000 +#define BOARD_ID_PIN_MASK 0x1000 +#define BOARD_REV_ID_PORT GPIOB + +#define BOARD_REV_1_0_BETA 0 +#define BOARD_REV_1_0_BETA_3 1 + +#define BOARD_REV_1_0_BETA_FREQ 8 +#define BOARD_REV_1_0_BETA_3_FREQ 16 + + +#endif /* INC_BOARD_CONFIG_H_ */ diff --git a/Downstream/Inc/build_config.h b/Downstream/Inc/build_config.h new file mode 100644 index 0000000..fe59f08 --- /dev/null +++ b/Downstream/Inc/build_config.h @@ -0,0 +1,29 @@ +/* + * build_config.h + * + * Created on: Jun 20, 2017 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_BUILD_CONFIG_H_ +#define INC_BUILD_CONFIG_H_ + + +#define CONFIG_MASS_STORAGE_ENABLED +#define CONFIG_MASS_STORAGE_WRITES_PERMITTED + +#define CONFIG_KEYBOARD_ENABLED +#define CONFIG_MOUSE_ENABLED + +#define CONFIG_READ_FLASH_TIME_MS 3000 //Enable read LED flashes for the specified length of time + +#define CONFIG_USB_ID_ENABLED + +#define CONFIG_FLASH_RDP_ENABLE + + +#endif /* INC_BUILD_CONFIG_H_ */ diff --git a/Downstream/Inc/downstream_hid.h b/Downstream/Inc/downstream_hid.h new file mode 100644 index 0000000..bd559cf --- /dev/null +++ b/Downstream/Inc/downstream_hid.h @@ -0,0 +1,70 @@ +/* + * downstream_hid.h + * + * Created on: Apr 10, 2016 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_DOWNSTREAM_HID_H_ +#define INC_DOWNSTREAM_HID_H_ + + +#include "downstream_interface_def.h" +#include "downstream_spi.h" +#include "usbh_def.h" + + +#define HID_MAX_REPORT_LEN 8 + +//These defines are duplicated in upstream_hid.h. Keep them in sync! +#define HID_MOUSE_INPUT_DATA_LEN 4 +#define HID_MOUSE_OUTPUT_DATA_LEN 0 +#define HID_MOUSE_MAX_BUTTONS 3 + +#define HID_KEYBOARD_INPUT_DATA_LEN 8 +#define HID_KEYBOARD_OUTPUT_DATA_LEN 1 +#define HID_KEYBOARD_MAX_KEY 101 //Also set in Upstream's HID report descriptor +#define HID_KEYBOARD_MAX_LED 3 + + +//Stuff for parsing HID descriptors: +#define HID_ITEM_LONG 0xFC +#define HID_ITEM_MASK 0xFC +#define HID_ITEM_LENGTH_MASK 0x03 + +#define HID_ITEM_USAGE_PAGE 0x04 //'global' usage page +#define HID_ITEM_USAGE_PAGE_BUTTON 0x09 +#define HID_ITEM_USAGE_PAGE_DESKTOP 0x01 + +#define HID_ITEM_COLLECTION 0xA0 +#define HID_ITEM_COLLECTION_PHYS 0x00 +#define HID_ITEM_END_COLLECTION 0xC0 + +#define HID_ITEM_USAGE 0x08 //'local' usage +#define HID_ITEM_USAGE_X 0x30 +#define HID_ITEM_USAGE_Y 0x31 +#define HID_ITEM_USAGE_WHEEL 0x38 + +#define HID_ITEM_REPORT_SIZE 0x74 //'global' report size +#define HID_ITEM_REPORT_COUNT 0x94 //'global' report count +#define HID_ITEM_REPORT_ID 0x84 + +#define HID_ITEM_INPUT 0x80 //'main' input +#define HID_ITEM_INPUT_ABS 0x02 +#define HID_ITEM_INPUT_REL 0x06 + + +typedef void (*TransactionCompleteCallbackTypeDef)(USBH_StatusTypeDef result); + +InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void); +void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); +void Downstream_HID_InterruptReportCallback(USBH_StatusTypeDef result); +void Downstream_HID_SendReportCallback(USBH_StatusTypeDef result); + + + +#endif /* INC_DOWNSTREAM_HID_H_ */ diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h new file mode 100644 index 0000000..eec61a8 --- /dev/null +++ b/Downstream/Inc/downstream_interface_def.h @@ -0,0 +1,77 @@ +/* + * downstream_interface_def.h + * + * Created on: 24/07/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_DOWNSTREAM_INTERFACE_DEF_H_ +#define INC_DOWNSTREAM_INTERFACE_DEF_H_ + + +//*************** +// Attention! +// Keep this file synchronised with upstream_interface_def.h +// in the Upstream project. +//*************** + + + +#define COMMAND_CLASS_DATA_FLAG 0x80 +#define COMMAND_CLASS_MASK ((uint8_t)(~COMMAND_CLASS_DATA_FLAG)) + + +typedef enum +{ + COMMAND_CLASS_INTERFACE, + COMMAND_CLASS_MASS_STORAGE, + COMMAND_CLASS_HID_MOUSE, + COMMAND_CLASS_HID_KEYBOARD, + //... + COMMAND_CLASS_ERROR +} +InterfaceCommandClassTypeDef; + + +typedef enum +{ + COMMAND_INTERFACE_ECHO, //Returns echo packet including all data + COMMAND_INTERFACE_NOTIFY_DEVICE //Returns COMMAND_CLASS_*** byte when downstream USB device is connected +} +InterfaceCommandInterfaceTypeDef; + + +typedef enum +{ + COMMAND_MSC_TEST_UNIT_READY, //Returns HAL_StatusTypeDef result + COMMAND_MSC_GET_CAPACITY, //Returns uint32_t blk_nbr, uint32_t blk_size + COMMAND_MSC_READ, //Returns data stream or error packet + COMMAND_MSC_WRITE, //Waits for data stream or returns error packet + COMMAND_MSC_DISCONNECT, //Returns same packet after sending Stop command to device + COMMAND_MSC_POLL_DISCONNECT //Returns same packet if device is still connected +} +InterfaceCommandMscTypeDef; + + +typedef enum +{ + COMMAND_HID_GET_REPORT, //Returns HID report from device + COMMAND_HID_SET_REPORT //Sends HID report to device. Simple ack packet contains no data. +} +InterfaceCommandHidTypeDef; + + +typedef enum +{ + COMMAND_ERROR_GENERIC, //Something went wrong, time to FREAKOUT + COMMAND_ERROR_DEVICE_DISCONNECTED, //Device unexpectedly disconnected +} +InterfaceCommandErrorTypeDef; + + + +#endif /* INC_DOWNSTREAM_INTERFACE_DEF_H_ */ diff --git a/Downstream/Inc/downstream_msc.h b/Downstream/Inc/downstream_msc.h new file mode 100644 index 0000000..d78c226 --- /dev/null +++ b/Downstream/Inc/downstream_msc.h @@ -0,0 +1,36 @@ +/* + * downstream_msc.h + * + * Created on: 8/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_DOWNSTREAM_MSC_H_ +#define INC_DOWNSTREAM_MSC_H_ + + +#include "downstream_interface_def.h" +#include "downstream_spi.h" + + +#define MSC_SUPPORTED_BLOCK_SIZE 512 +#define MSC_FIXED_LUN 0 + + +typedef void (*DownstreamMSCCallbackPacketTypeDef)(DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength8); + + +InterfaceCommandClassTypeDef Downstream_MSC_ApproveConnectedDevice(void); +void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); +HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* packetToSend, + uint32_t dataLength8); +HAL_StatusTypeDef Downstream_MSC_GetStreamDataPacket(DownstreamMSCCallbackPacketTypeDef callback); + + + +#endif /* INC_DOWNSTREAM_MSC_H_ */ diff --git a/Downstream/Inc/downstream_spi.h b/Downstream/Inc/downstream_spi.h new file mode 100644 index 0000000..6f59a6f --- /dev/null +++ b/Downstream/Inc/downstream_spi.h @@ -0,0 +1,84 @@ +/* + * downstream_spi.h + * + * Created on: 24/07/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_DOWNSTREAM_SPI_H_ +#define INC_DOWNSTREAM_SPI_H_ + + +#include "usbh_config.h" + + +#define DOWNSTREAM_PACKET_HEADER_LEN (2) //Min length = CommandClass & Command bytes +#define DOWNSTREAM_PACKET_LEN (DOWNSTREAM_PACKET_HEADER_LEN + BOT_PAGE_LENGTH) +#define DOWNSTREAM_PACKET_LEN_MIN (DOWNSTREAM_PACKET_HEADER_LEN) + +#define DOWNSTREAM_PACKET_HEADER_LEN_16 (DOWNSTREAM_PACKET_HEADER_LEN / 2) +#define DOWNSTREAM_PACKET_LEN_16 (DOWNSTREAM_PACKET_LEN / 2) +#define DOWNSTREAM_PACKET_LEN_MIN_16 (DOWNSTREAM_PACKET_LEN_MIN / 2) + +#define DOWNSTREAM_SPI_FREAKOUT \ + do { \ + Downstream_PacketProcessor_FreakOut(); \ + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \ + while (1); \ + } while (0); + + + +typedef enum +{ + DOWNSTREAM_INTERFACE_IDLE, + DOWNSTREAM_INTERFACE_RX_SIZE_WAIT, + DOWNSTREAM_INTERFACE_RX_PACKET_WAIT, + DOWNSTREAM_INTERFACE_TX_SIZE_WAIT, + DOWNSTREAM_INTERFACE_TX_PACKET_WAIT, + DOWNSTREAM_INTERFACE_ERROR +} +InterfaceStateTypeDef; + + +typedef enum +{ + NOT_BUSY, + BUSY +} +PacketBusyTypeDef; + + +typedef struct +{ + PacketBusyTypeDef Busy; //Everything after Busy should be word-aligned + uint16_t Length16 __ALIGN_END; //Packet length includes CommandClass, Command, and Data + uint8_t CommandClass; + uint8_t Command; + uint8_t Data[BOT_PAGE_LENGTH]; //Should (must?) be word-aligned, for USB copy routine +} +DownstreamPacketTypeDef; + + + +typedef void (*FreePacketCallbackTypeDef)(DownstreamPacketTypeDef* freePacket); +typedef void (*SpiPacketReceivedCallbackTypeDef)(DownstreamPacketTypeDef* receivedPacket); + + +void Downstream_InitSPI(void); +HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback); +DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void); +void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease); +HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback); +HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite); +void Downstream_SPIProcess(void); + +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); + + +#endif /* INC_DOWNSTREAM_SPI_H_ */ diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h new file mode 100644 index 0000000..deff744 --- /dev/null +++ b/Downstream/Inc/downstream_statemachine.h @@ -0,0 +1,54 @@ +/* + * downstream_statemachine.h + * + * Created on: 2/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_DOWNSTREAM_STATEMACHINE_H_ +#define INC_DOWNSTREAM_STATEMACHINE_H_ + + +#include "usbh_def.h" +#include "usb_host.h" +#include "downstream_spi.h" + + +typedef enum +{ + STATE_DEVICE_NOT_READY, + STATE_DEVICE_READY, //Go here if HOST_USER_CLASS_ACTIVE callback arrives first + STATE_WAIT_DEVICE_READY, //Go here if COMMAND_INTERFACE_NOTIFY_DEVICE message arrives first + STATE_ACTIVE, + STATE_ERROR +} DownstreamStateTypeDef; + + + +#define DOWNSTREAM_STATEMACHINE_FREAKOUT \ + do { \ + USB_Host_Disconnect(); \ + LED_SetState(LED_STATUS_FLASH_ERROR); \ + /*DownstreamState = STATE_ERROR; */ \ + while (1); \ +} while (0); + + + + +void Downstream_InitStateMachine(void); +void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id); +void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); +void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket); +void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket); +void Downstream_PacketProcessor_NotifyDisconnectReplyRequired(void); +void Downstream_PacketProcessor_CheckNotifyDisconnectReply(void); +void Downstream_PacketProcessor_SetErrorState(void); +void Downstream_PacketProcessor_FreakOut(void); + + +#endif /* INC_DOWNSTREAM_STATEMACHINE_H_ */ diff --git a/Downstream/Inc/hal_config.h b/Downstream/Inc/hal_config.h new file mode 100644 index 0000000..18ea4ab --- /dev/null +++ b/Downstream/Inc/hal_config.h @@ -0,0 +1,423 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2015 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +//#define HAL_ADC_MODULE_ENABLED +//#define HAL_CAN_MODULE_ENABLED +//#define HAL_CRC_MODULE_ENABLED +//#define HAL_CRYP_MODULE_ENABLED +//#define HAL_DAC_MODULE_ENABLED +//#define HAL_DCMI_MODULE_ENABLED +//#define HAL_DMA2D_MODULE_ENABLED +//#define HAL_ETH_MODULE_ENABLED +//#define HAL_NAND_MODULE_ENABLED +//#define HAL_NOR_MODULE_ENABLED +//#define HAL_PCCARD_MODULE_ENABLED +//#define HAL_SRAM_MODULE_ENABLED +//#define HAL_SDRAM_MODULE_ENABLED +//#define HAL_HASH_MODULE_ENABLED +//#define HAL_I2C_MODULE_ENABLED +//#define HAL_I2S_MODULE_ENABLED +//#define HAL_IWDG_MODULE_ENABLED +//#define HAL_LTDC_MODULE_ENABLED +//#define HAL_RNG_MODULE_ENABLED +//#define HAL_RTC_MODULE_ENABLED +//#define HAL_SAI_MODULE_ENABLED +//#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +//#define HAL_TIM_MODULE_ENABLED +//#define HAL_UART_MODULE_ENABLED +//#define HAL_USART_MODULE_ENABLED +//#define HAL_IRDA_MODULE_ENABLED +//#define HAL_SMARTCARD_MODULE_ENABLED +//#define HAL_WWDG_MODULE_ENABLED +//#define HAL_PCD_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +//#define HAL_QSPI_MODULE_ENABLED +//#define HAL_QSPI_MODULE_ENABLED +//#define HAL_CEC_MODULE_ENABLED +//#define HAL_FMPI2C_MODULE_ENABLED +//#define HAL_SPDIFRX_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000) +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority */ +#define USE_RTOS 0 +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define DATA_CACHE_ENABLE 1 + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2 +#define MAC_ADDR1 0 +#define MAC_ADDR2 0 +#define MAC_ADDR3 0 +#define MAC_ADDR4 0 +#define MAC_ADDR5 0 + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01 +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FF) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) + +#define PHY_READ_TO ((uint32_t)0x0000FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Inc/interrupts.h b/Downstream/Inc/interrupts.h new file mode 100644 index 0000000..35e9584 --- /dev/null +++ b/Downstream/Inc/interrupts.h @@ -0,0 +1,72 @@ +/** + ****************************************************************************** + * @file stm32f4xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_IT_H +#define __STM32F4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +#define INT_PRIORITY_SYSTICK 2 +#define INT_PRIORITY_SPI_DMA 10 +//#define INT_PRIORITY_SPI 8 //Interrupt-based SPI must be highest priority! +#define INT_PRIORITY_USB 10 + + + /* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void SysTick_Handler(void); +void DMA2_Stream2_IRQHandler(void); +void DMA2_Stream3_IRQHandler(void); +void OTG_FS_IRQHandler(void); +void BusFault_Handler(void); + +void EnableOneBusFault(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Inc/led.h b/Downstream/Inc/led.h new file mode 100644 index 0000000..b79fc91 --- /dev/null +++ b/Downstream/Inc/led.h @@ -0,0 +1,47 @@ +/* + * led.h + * + * Created on: 19/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef INC_LED_H_ +#define INC_LED_H_ + + +#include "stm32f4xx_hal.h" + + +typedef enum +{ + LED_STATUS_STARTUP, + LED_STATUS_OFF, + LED_STATUS_FLASH_ERROR, + LED_STATUS_FLASH_UNSUPPORTED, + LED_STATUS_FLASH_BOTDETECT, + LED_STATUS_FLASH_READWRITE +} +LedStatusTypeDef; + + +void LED_Init(void); +void LED_SetState(LedStatusTypeDef newState); +void LED_Tick(void); + + +#define STARTUP_FLASH_DELAY_MS 500 + +#define LED_ERROR_BLINK_MS 100 +#define LED_UNSUPPORTED_BLINK_MS 500 +#define LED_BOTDETECT_ON_MS 100 +#define LED_BOTDETECT_OFF_MS (1000 - (LED_BOTDETECT_ON_MS * 3)) //Two flashes, total period = 1 sec +#define LED_READWRITE_ON_MS 10 +#define LED_READWRITE_OFF_MS 30 + + + +#endif /* INC_LED_H_ */ diff --git a/Downstream/Inc/usb_host.h b/Downstream/Inc/usb_host.h new file mode 100644 index 0000000..c07de96 --- /dev/null +++ b/Downstream/Inc/usb_host.h @@ -0,0 +1,66 @@ +/** + ****************************************************************************** + * @file : USB_HOST + * @version : v1.0_Cube + * @brief : Header for usb_host file. + ****************************************************************************** + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __usb_host_H +#define __usb_host_H +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" + + +void USB_Host_Init(void); +void USB_Host_Process(void); +void USB_Host_Disconnect(void); + + +#ifdef __cplusplus +} +#endif +#endif /*__usb_host_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Inc/usbh_config.h b/Downstream/Inc/usbh_config.h new file mode 100644 index 0000000..96f98eb --- /dev/null +++ b/Downstream/Inc/usbh_config.h @@ -0,0 +1,179 @@ +/** + ****************************************************************************** + * @file : usbh_conf.h + * @version : v1.0_Cube + * @brief : Header for usbh_conf file. + ****************************************************************************** + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** +*/ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBH_CONF__H__ +#define __USBH_CONF__H__ +#include +#include +#include +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" + +/** + MiddleWare name : USB_HOST + MiddleWare fileName : usbh_conf.h + MiddleWare version : +*/ +/*---------- -----------*/ +#define USBH_MAX_NUM_ENDPOINTS 2 + +/*---------- -----------*/ +#define USBH_MAX_NUM_INTERFACES 3 + +/*---------- -----------*/ +#define USBH_MAX_NUM_CONFIGURATION 1 + +/*---------- -----------*/ +#define USBH_KEEP_CFG_DESCRIPTOR 0 + +/*---------- -----------*/ +#define USBH_MAX_NUM_SUPPORTED_CLASS 2 + +/*---------- -----------*/ +#define USBH_MAX_SIZE_CONFIGURATION 256 + +/*---------- -----------*/ +#define USBH_MAX_DATA_BUFFER 256 //was 512, string descriptors are max 255 bytes + +/*---------- -----------*/ +#define USBH_DEBUG_LEVEL 0 + +/*---------- -----------*/ +#define USBH_USE_OS 0 + + +#define BOT_PAGE_LENGTH 512 //Moved here from usbh_msc_bot.h to avoid a circular include loop :( + + +/****************************************/ +/* #define for FS and HS identification */ +#define HOST_HS 0 +#define HOST_FS 1 + +/** @defgroup USBH_Exported_Macros + * @{ + */ +#if (USBH_USE_OS == 1) + #include "cmsis_os.h" + #define USBH_PROCESS_PRIO osPriorityNormal + #define USBH_PROCESS_STACK_SIZE ((uint16_t)0) +#endif + + /* Memory management macros */ +#define USBH_malloc malloc +#define USBH_free free +#define USBH_memset memset +#define USBH_memcpy memcpy + + /* DEBUG macros */ + +#if (USBH_DEBUG_LEVEL > 0) +#define USBH_UsrLog(...) printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBH_UsrLog(...) +#endif + + +#if (USBH_DEBUG_LEVEL > 1) + +#define USBH_ErrLog(...) printf("ERROR: ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBH_ErrLog(...) +#endif + + +#if (USBH_DEBUG_LEVEL > 2) +#define USBH_DbgLog(...) printf("DEBUG : ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBH_DbgLog(...) +#endif + +/** + * @} + */ + + + +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + +#endif //__USBH_CONF__H__ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h new file mode 100644 index 0000000..9cf0f8b --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid.h @@ -0,0 +1,362 @@ +/** + ****************************************************************************** + * @file usbh_hid.h + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file contains all the prototypes for the usbh_hid.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + * + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HID_H +#define __USBH_HID_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "downstream_hid.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.c + * @{ + */ + + +/** @defgroup USBH_HID_CORE_Exported_Types + * @{ + */ + +#define HID_MIN_POLL 10 +#define HID_MAX_REPORT_SIZE 8 +#define HID_REPORT_BUFFER_SIZE 64 +#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 + + +#define HID_REPORT_DIRECTION_IN 0x01 +#define HID_REPORT_DIRECTION_OUT 0x02 + + +/* States for HID State Machine */ +typedef enum +{ + HID_INIT= 0, + HID_IDLE, + HID_GET_DATA, + HID_GET_POLL, + HID_SET_DATA_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; + uint8_t OutEp; + uint8_t InEp; + HID_StateTypeDef state; + HID_CtlStateTypeDef ctl_state; + uint16_t length; + uint16_t poll; + uint32_t timer; + uint8_t ep_addr; + uint8_t Protocol; + HID_DescTypeDef HID_Desc; + TransactionCompleteCallbackTypeDef ReportCallback; + uint8_t Data[HID_REPORT_BUFFER_SIZE]; +} +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_PROTOCOL 0x01 +#define HID_MOUSE_PROTOCOL 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, + TransactionCompleteCallbackTypeDef callback); + +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); + +uint8_t USBH_HID_GetPollInterval(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); + +HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, + TransactionCompleteCallbackTypeDef callback); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_keybd.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_keybd.h new file mode 100644 index 0000000..06de452 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_keybd.h @@ -0,0 +1,326 @@ +/** + ****************************************************************************** + * @file usbh_hid_keybd.h + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file contains all the prototypes for the usbh_hid_keybd.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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 + +#ifdef __cplusplus + extern "C" { +#endif + +/* 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); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_KEYBD_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_mouse.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_mouse.h new file mode 100644 index 0000000..e8bf542 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_mouse.h @@ -0,0 +1,125 @@ +/** + ****************************************************************************** + * @file usbh_hid_mouse.h + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file contains all the prototypes for the usbh_hid_mouse.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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 + +#ifdef __cplusplus + extern "C" { +#endif + +/* 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); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_MOUSE_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_parser.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_parser.h new file mode 100644 index 0000000..b5dc79f --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_parser.h @@ -0,0 +1,106 @@ +/** + ****************************************************************************** + * @file usbh_hid_parser.c + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file is the header file of the usbh_hid_parser.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_PARSER_H +#define __USBH_HID_PARSER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* 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); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_PARSER_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_usage.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_usage.h new file mode 100644 index 0000000..df65995 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc/usbh_hid_usage.h @@ -0,0 +1,200 @@ +/** + ****************************************************************************** + * @file usbh_hid_usage.c + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file contain the USAGE page codes + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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 __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @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 Desktop" 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 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USDH_HID_USAGE_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c new file mode 100644 index 0000000..ed26caa --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c @@ -0,0 +1,850 @@ +/** + ****************************************************************************** + * @file usbh_hid.c + * @author MCD Application Team + * @version V3.2.2 + * @date 07-July-2015 + * @brief This file is the HID Layer Handlers for USB Host HID class. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the HID 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 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid.h" +#include "build_config.h" + + +#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + +/** @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); + + +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 = 0xFF; + + HID_HandleTypeDef *HID_Handle; + + +#ifdef CONFIG_MOUSE_ENABLED + interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, HID_MOUSE_PROTOCOL); //Search for mouse interfaces first +#endif +#ifdef CONFIG_KEYBOARD_ENABLED + if (interface == 0xFF) + { + interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, HID_KEYBRD_PROTOCOL); + } +#endif + + if(interface == 0xFF) /* No Valid Interface */ + { + USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name); + return USBH_FAIL; + } + + USBH_SelectInterface (phost, interface); + phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc (sizeof(HID_HandleTypeDef)); + HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + 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; + HID_Handle->Protocol = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol; + + if (HID_Handle->poll < HID_MIN_POLL) HID_Handle->poll = HID_MIN_POLL; + if (HID_Handle->length > HID_REPORT_BUFFER_SIZE) return USBH_FAIL; //Some mechanical keyboards need to send > 8 byte packets + + /* 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); + } + + } + return USBH_OK; +} + +/** + * @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 = (HID_HandleTypeDef *) 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 = (HID_HandleTypeDef *) 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 descriptor 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: + //Mouse in 'report' mode, + //Keyboard in 'boot' mode + if (USBH_HID_SetProtocol(phost, + (HID_Handle->Protocol == HID_MOUSE_PROTOCOL ? 1 : 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_URBStateTypeDef urbStatus; + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + switch (HID_Handle->state) + { + case HID_INIT: + HID_Handle->timer = phost->Timer; + HID_Handle->state = HID_IDLE; + break; + + case HID_IDLE: + break; + + case HID_GET_DATA: + if ((int32_t)(phost->Timer - HID_Handle->timer) >= HID_Handle->poll) + { + USBH_InterruptReceiveData(phost, + HID_Handle->Data, + HID_Handle->length, + HID_Handle->InPipe); + HID_Handle->state = HID_GET_POLL; + HID_Handle->timer = phost->Timer; + } + break; + + case HID_GET_POLL: + urbStatus = USBH_LL_GetURBState(phost, HID_Handle->InPipe); + + if (urbStatus == USBH_URB_DONE) + { + HID_Handle->ReportCallback(USBH_OK); + HID_Handle->state = HID_IDLE; + break; + } + + if (urbStatus == USBH_URB_NOTREADY) + { + HID_Handle->ReportCallback(USBH_BUSY); + HID_Handle->state = HID_IDLE; + break; + } + + if (urbStatus == USBH_URB_STALL) + { + /* Issue Clear Feature on interrupt IN endpoint */ + if(USBH_ClrFeature(phost, + HID_Handle->ep_addr) == USBH_OK) + { + HID_Handle->ReportCallback(USBH_BUSY); + HID_Handle->state = HID_IDLE; + } + } + break; + + case HID_SET_DATA_POLL: + if (USBH_CtlReq(phost, HID_Handle->Data, phost->Control.setup.b.wLength.w) == USBH_OK) + { + HID_Handle->ReportCallback(USBH_OK); + HID_Handle->state = HID_IDLE; + } + break; + + default: + break; + } + return USBH_OK; +} + +/** + * @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) +{ + + return USBH_OK; +} + + + +//Downstream_HID calls into here at main() priority, +//to request a new report for Upstream. +HAL_StatusTypeDef USBH_HID_GetInterruptReport(USBH_HandleTypeDef *phost, + TransactionCompleteCallbackTypeDef callback) +{ + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + if (HID_Handle->state == HID_IDLE) + { + HID_Handle->ReportCallback = callback; + HID_Handle->state = HID_GET_DATA; + return HAL_OK; + } + + //return HAL_ERROR; + while (1); +} + + + + +/** +* @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; + + if (length > USBH_MAX_DATA_BUFFER) + { + length = USBH_MAX_DATA_BUFFER; + } + + status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD, + USB_DESC_HID_REPORT, + phost->device.current_interface, + 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; + + if (length > USBH_MAX_DATA_BUFFER) + { + length = USBH_MAX_DATA_BUFFER; + } + + status = USBH_GetDescriptor( phost, + USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD, + USB_DESC_HID, + phost->device.current_interface, + 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 : Targeted report ID for Set Idle request + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost, + uint8_t duration, + uint8_t reportId) +{ + if (phost->RequestState == CMD_SEND) + { + 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 : Targeted 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, + TransactionCompleteCallbackTypeDef callback) +{ + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + uint32_t i; + + if (phost->RequestState == CMD_SEND) + { + if ((HID_Handle->state != HID_IDLE) || + (reportLen > HID_MAX_REPORT_SIZE)) + { + while (1); + } + + HID_Handle->ReportCallback = callback; + HID_Handle->state = HID_SET_DATA_POLL; + for (i = 0; i < reportLen; i++) + { + HID_Handle->Data[i] = *reportBuff; + reportBuff++; + } + + 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); + return USBH_OK; +} + + +/** + * @brief USBH_HID_GetReport + * retreive Set Report + * @param phost: Host handle + * @param reportType : Report type to be sent + * @param reportId : Targeted 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) +{ + if (phost->RequestState == CMD_SEND) + { + 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) +{ + if (phost->RequestState == CMD_SEND) + { + 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_PROTOCOL) + { + type = HID_KEYBOARD; + } + else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \ + == HID_MOUSE_PROTOCOL) + { + type= HID_MOUSE; + } + } + return type; +} + + +/** + * @brief USBH_HID_GetPollInterval + * Return HID device poll time + * @param phost: Host handle + * @retval poll time (ms) + */ +uint8_t USBH_HID_GetPollInterval(USBH_HandleTypeDef *phost) +{ + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + if((phost->gState == HOST_CLASS_REQUEST) || + (phost->gState == HOST_INPUT) || + (phost->gState == HOST_SET_CONFIGURATION) || + (phost->gState == HOST_CHECK_CLASS) || + ((phost->gState == HOST_CLASS))) + { + return (HID_Handle->poll); + } + else + { + return 0; + } +} +/** + * @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 = (uint8_t*) 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 = (const uint8_t*) 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) +{ + +} + +#endif //#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h new file mode 100644 index 0000000..b49884b --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h @@ -0,0 +1,241 @@ +/** + ****************************************************************************** + * @file usbh_msc.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file contains all the prototypes for the usbh_msc.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_H +#define __USBH_MSC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_msc_bot.h" +#include "usbh_msc_scsi.h" + + + + +typedef enum +{ + MSC_INIT = 0, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_REQUEST_SENSE_WAIT_RETRY, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_START_STOP, +} +MSC_StateTypeDef; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, + +} +MSC_ErrorTypeDef; + +typedef enum +{ + MSC_REQ_IDLE = 0, + MSC_REQ_STARTUP_DELAY, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_RESET, + MSC_REQ_ERROR, +} +MSC_ReqStateTypeDef; + +#ifndef MAX_SUPPORTED_LUN + #define MAX_SUPPORTED_LUN 2 +#endif + + +/* Structure for LUN */ +typedef struct +{ + MSC_StateTypeDef state; + MSC_ErrorTypeDef error; + USBH_StatusTypeDef prev_ready_state; + SCSI_CapacityTypeDef capacity; + SCSI_SenseTypeDef sense; + SCSI_StdInquiryDataTypeDef inquiry; + uint8_t state_changed; + +} +MSC_LUNTypeDef; + + +typedef void (*MSC_CmdCompleteCallback)(USBH_StatusTypeDef result); + +/* 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 timeout; + uint32_t retry_timeout; + MSC_CmdCompleteCallback CmdCompleteCallback; +} +MSC_HandleTypeDef; + + +/** + * @} + */ + + + +/** @defgroup USBH_MSC_CORE_Exported_Defines + * @{ + */ + +#define USB_REQ_BOT_RESET 0xFF +#define USB_REQ_GET_MAX_LUN 0xFE + +#define MSC_TIMEOUT_FIXED_MS 10000 //Some flash drives take 2 seconds to write a single block! +#define MSC_SAMSUNG_STARTUP_DELAY_MS 100 //Samsung FIT Plus 32GB USB 3.1 flash drive was here + +/* MSC Class Codes */ +#define USB_MSC_CLASS 0x08 + +/* Interface Descriptor field values for MSC Protocol */ +#define MSC_BOT 0x50 +#define MSC_TRANSPARENT 0x06 + +#define MSC_STARTUP_TIMEOUT_MS 15000 +#define MSC_STARTUP_RETRY_TIME_MS 100 + +#define MSC_START_STOP_EJECT_FLAG 0 +#define MSC_START_STOP_LOAD_FLAG 1 + +/** + * @} + */ + +/** @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, + MSC_CmdCompleteCallback callback); + +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, + uint32_t length, + MSC_CmdCompleteCallback callback); + +USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint32_t length, + MSC_CmdCompleteCallback callback); + +USBH_StatusTypeDef USBH_MSC_StartStopUnit(USBH_HandleTypeDef *phost, + uint8_t lun, + uint8_t startStop, + MSC_CmdCompleteCallback callback); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h new file mode 100644 index 0000000..0a57b5b --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h @@ -0,0 +1,249 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_msc_bot.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_BOT_H +#define __USBH_MSC_BOT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "downstream_spi.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_BOT + * @brief This file is the Header file for usbh_msc_bot.c + * @{ + */ + + +/** @defgroup USBH_MSC_BOT_Exported_Types + * @{ + */ + +typedef enum { + BOT_OK = 0, + BOT_FAIL = 1, + BOT_PHASE_ERROR = 2, + BOT_BUSY = 3 +} +BOT_StatusTypeDef; + +typedef enum { + BOT_CMD_IDLE = 0, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} +BOT_CMDStateTypeDef; + +/* CSW Status Definitions */ +typedef enum +{ + + BOT_CSW_CMD_PASSED = 0x00, + BOT_CSW_CMD_FAILED = 0x01, + BOT_CSW_PHASE_ERROR = 0x02, +} +BOT_CSWStatusTypeDef; + +typedef enum { + BOT_SEND_CBW = 1, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT_FREE_PACKET, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT_RECEIVE_PACKET, + 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; + DownstreamPacketTypeDef* bot_packet; + uint8_t* bot_packet_pbuf; + uint16_t bot_packet_bytes_remaining; + uint16_t this_URB_size; +} +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_CBW_CB_LENGTH 16 + + +#define USB_REQ_BOT_RESET 0xFF +#define USB_REQ_GET_MAX_LUN 0xFE + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk + Endpoint continuously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun); + +USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun); +USBH_StatusTypeDef USBH_MSC_BOT_Error(USBH_HandleTypeDef *phost, uint8_t lun); + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_BOT_H__ */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h new file mode 100644 index 0000000..c1a20e7 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h @@ -0,0 +1,232 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_msc_scsi.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_MSC_CLASS + * @{ + */ + +/** @defgroup USBH_MSC_SCSI + * @brief This file is the Header file for usbh_msc_scsi.c + * @{ + */ + + +// Capacity data. +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} SCSI_CapacityTypeDef; + + +// Sense data. +typedef struct +{ + uint8_t key; + uint8_t asc; + uint8_t ascq; +} SCSI_SenseTypeDef; + +// INQUIRY data. +typedef struct +{ + uint8_t PeripheralQualifier; + uint8_t DeviceType; + uint8_t RemovableMedia; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +}SCSI_StdInquiryDataTypeDef; + +/** @defgroup USBH_MSC_SCSI_Exported_Defines + * @{ + */ +#define OPCODE_TEST_UNIT_READY 0x00 +#define OPCODE_READ_CAPACITY10 0x25 +#define OPCODE_READ10 0x28 +#define OPCODE_WRITE10 0x2A +#define OPCODE_REQUEST_SENSE 0x03 +#define OPCODE_INQUIRY 0x12 +#define OPCODE_START_STOP_UNIT 0x1B + +#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 DATA_LEN_START_STOP_UNIT 0 + +#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, + uint32_t length); + +USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint32_t length); + +USBH_StatusTypeDef USBH_MSC_SCSI_StartStopUnit (USBH_HandleTypeDef *phost, + uint8_t lun, + uint8_t startStop); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_MSC_SCSI_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c new file mode 100644 index 0000000..876a10b --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c @@ -0,0 +1,892 @@ +/** + ****************************************************************************** + * @file usbh_msc.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements the MSC class driver functions + * =================================================================== + * MSC Class Description + * =================================================================== + * This module manages the MSC class V1.0 following the "Universal + * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 + * Sep. 31, 1999". + * This driver implements the following aspects of the specification: + * - Bulk-Only Transport protocol + * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3)) + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_msc.h" +#include "usbh_msc_bot.h" +#include "usbh_msc_scsi.h" +#include "interrupts.h" +#include "build_config.h" + + +#ifdef CONFIG_MASS_STORAGE_ENABLED +/** @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, 0xFF, MSC_BOT);//MSC_TRANSPARENT, MSC_BOT); //Ignore subclass?!! + + if(interface == 0xFF) /* Not Valid Interface */ + { + USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name); + status = USBH_FAIL; + } + else + { + USBH_SelectInterface (phost, interface); + + phost->pActiveClass->pData = (MSC_HandleTypeDef *)USBH_malloc (sizeof(MSC_HandleTypeDef)); + MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress & 0x80) + { + MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress); + MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize; + } + else + { + MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress); + MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize; + } + + if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress & 0x80) + { + MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress); + MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize; + } + else + { + MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress); + MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize; + } + + MSC_Handle->current_lun = 0; + MSC_Handle->rw_lun = 0; + MSC_Handle->state = MSC_INIT; + MSC_Handle->error = MSC_OK; + MSC_Handle->req_state = MSC_REQ_IDLE; + MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp); + MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp); + MSC_Handle->CmdCompleteCallback = NULL; + + USBH_MSC_BOT_Init(phost); + + /* De-Initialize LUNs information */ + USBH_memset(MSC_Handle->unit, 0, sizeof(MSC_Handle->unit)); + + /* Open the new channels */ + USBH_OpenPipe (phost, + MSC_Handle->OutPipe, + MSC_Handle->OutEp, + phost->device.address, + phost->device.speed, + USB_EP_TYPE_BULK, + MSC_Handle->OutEpSize); + + USBH_OpenPipe (phost, + MSC_Handle->InPipe, + MSC_Handle->InEp, + phost->device.address, + phost->device.speed, + USB_EP_TYPE_BULK, + MSC_Handle->InEpSize); + + + USBH_LL_SetToggle (phost, MSC_Handle->InPipe,0); + USBH_LL_SetToggle (phost, MSC_Handle->OutPipe,0); + status = USBH_OK; + } + return status; +} + +/** + * @brief USBH_MSC_InterfaceDeInit + * The function DeInit the Pipes used for the MSC class. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ( MSC_Handle->OutPipe) + { + USBH_ClosePipe(phost, MSC_Handle->OutPipe); + USBH_FreePipe (phost, MSC_Handle->OutPipe); + MSC_Handle->OutPipe = 0; /* Reset the Channel as Free */ + } + + if ( MSC_Handle->InPipe) + { + USBH_ClosePipe(phost, MSC_Handle->InPipe); + USBH_FreePipe (phost, MSC_Handle->InPipe); + MSC_Handle->InPipe = 0; /* Reset the Channel as Free */ + } + + if(phost->pActiveClass->pData) + { + USBH_free (phost->pActiveClass->pData); + phost->pActiveClass->pData = 0; + } + + return USBH_OK; +} + +/** + * @brief USBH_MSC_ClassRequest + * The function is responsible for handling Standard requests + * for MSC class. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef status = USBH_BUSY; + + /* Switch MSC REQ state machine */ + switch (MSC_Handle->req_state) + { + case MSC_REQ_IDLE: + MSC_Handle->timeout = HAL_GetTick(); + MSC_Handle->req_state = MSC_REQ_STARTUP_DELAY; + break; + + case MSC_REQ_STARTUP_DELAY: + if ((HAL_GetTick() - MSC_Handle->timeout) > MSC_SAMSUNG_STARTUP_DELAY_MS) + { + MSC_Handle->req_state = MSC_REQ_GET_MAX_LUN; + } + break; + + case MSC_REQ_GET_MAX_LUN: + /* Issue GetMaxLUN request */ + status = USBH_MSC_BOT_REQ_GetMaxLUN(phost, (uint8_t *)&MSC_Handle->max_lun); + + /* When devices do not support the GetMaxLun request, this should + be considred as only one logical unit is supported */ + if(status == USBH_NOT_SUPPORTED) + { + MSC_Handle->max_lun = 0; + status = USBH_OK; + } + + if(status == USBH_OK) + { + MSC_Handle->max_lun = (uint8_t )(MSC_Handle->max_lun) + 1; + USBH_UsrLog ("Number of supported LUN: %lu", (int32_t)(MSC_Handle->max_lun)); + + if (MSC_Handle->max_lun > MAX_SUPPORTED_LUN) + { + MSC_Handle->max_lun = MAX_SUPPORTED_LUN; + } + MSC_Handle->req_state = MSC_REQ_IDLE; + } + break; + + case MSC_REQ_ERROR : + /* a Clear Feature should be issued here */ + if(USBH_ClrFeature(phost, 0x00) == USBH_OK) + { + MSC_Handle->req_state = MSC_Handle->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/** + * @brief USBH_MSC_Process + * The function is for managing state machine for MSC data transfers + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef error = USBH_BUSY ; + USBH_StatusTypeDef scsi_status = USBH_BUSY ; + USBH_StatusTypeDef ready_status = USBH_BUSY ; + + + switch (MSC_Handle->state) + { + case MSC_INIT: + + if(MSC_Handle->current_lun < MSC_Handle->max_lun) + { + + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; + /* Switch MSC REQ state machine */ + switch (MSC_Handle->unit[MSC_Handle->current_lun].state) + { + case MSC_INIT: + USBH_UsrLog ("LUN #%d: ", MSC_Handle->current_lun); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY; + MSC_Handle->timeout = HAL_GetTick(); + //Fallthrough + + case MSC_READ_INQUIRY: + scsi_status = USBH_MSC_SCSI_Inquiry(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry); + + if( scsi_status == USBH_OK) + { + USBH_UsrLog ("Inquiry Vendor : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.vendor_id); + USBH_UsrLog ("Inquiry Product : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.product_id); + USBH_UsrLog ("Inquiry Version : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.revision_id); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; + } + if( scsi_status == USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + } + else if(scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + break; + + case MSC_TEST_UNIT_READY: + ready_status = USBH_MSC_SCSI_TestUnitReady(phost, MSC_Handle->current_lun); + + if( ready_status == USBH_OK) + { + if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_OK) + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1; + USBH_UsrLog ("MSC Device ready"); + } + else + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0; + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_CAPACITY10; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; + MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_OK; + } + if( ready_status == USBH_FAIL) + { + /* Media not ready, so try to check again during 10s */ + if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1; + USBH_UsrLog ("MSC Device NOT ready"); + } + else + { + MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0; + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; + MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_FAIL; + } + else if(ready_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + break; + + case MSC_READ_CAPACITY10: + scsi_status = USBH_MSC_SCSI_ReadCapacity(phost,MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].capacity) ; + + if(scsi_status == USBH_OK) + { + if(MSC_Handle->unit[MSC_Handle->current_lun].state_changed == 1) + { + USBH_UsrLog ("MSC Device capacity : %lu Bytes", \ + (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)); + USBH_UsrLog ("Block number : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr)); + USBH_UsrLog ("Block Size : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)); + } + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; + MSC_Handle->current_lun++; + } + else if( scsi_status == USBH_FAIL) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; + } + else if(scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = USBH_MSC_SCSI_RequestSense(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].sense); + + if( scsi_status == USBH_OK) + { + if((MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION) || + (MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY) ) + { + if((HAL_GetTick() - MSC_Handle->timeout) < MSC_STARTUP_TIMEOUT_MS) + { + MSC_Handle->retry_timeout = HAL_GetTick(); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE_WAIT_RETRY; + break; + } + } + + USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.key); + USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.asc); + USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.ascq); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->current_lun++; + } + if( scsi_status == USBH_FAIL) + { + USBH_UsrLog ("MSC Device NOT ready"); + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_UNRECOVERED_ERROR; + } + else if(scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; + } + break; + + case MSC_REQUEST_SENSE_WAIT_RETRY: + if ((HAL_GetTick() - MSC_Handle->retry_timeout) > MSC_STARTUP_RETRY_TIME_MS) + { + MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; + } + break; + + case MSC_UNRECOVERED_ERROR: + MSC_Handle->current_lun++; + break; + + default: + break; + } + } + else + { + MSC_Handle->current_lun = 0; + MSC_Handle->state = MSC_IDLE; + + phost->pUser(phost, HOST_USER_CLASS_ACTIVE); + } + break; + + case MSC_IDLE: + error = USBH_OK; + break; + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + case MSC_WRITE: +#endif + case MSC_READ: + error = USBH_MSC_RdWrProcess(phost, MSC_Handle->rw_lun); + if(((int32_t)(HAL_GetTick() - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) + { + error = USBH_FAIL; + } + + if (error != USBH_BUSY) + { + MSC_Handle->state = MSC_IDLE; + if (MSC_Handle->CmdCompleteCallback != NULL) + { + MSC_Handle->CmdCompleteCallback(error); + MSC_Handle->CmdCompleteCallback = NULL; + } + } + break; + + case MSC_TEST_UNIT_READY: + error = USBH_MSC_SCSI_TestUnitReady(phost, MSC_Handle->rw_lun); + + if (((int32_t)(HAL_GetTick() - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) + { + error = USBH_FAIL; + } + if (error != USBH_BUSY) + { + MSC_Handle->state = MSC_IDLE; + if (error == USBH_OK) + { + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; + } + else + { + MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; + } + if (MSC_Handle->CmdCompleteCallback != NULL) + { + MSC_Handle->CmdCompleteCallback(error); + MSC_Handle->CmdCompleteCallback = NULL; + } + } + break; + + case MSC_START_STOP: + error = USBH_MSC_SCSI_StartStopUnit(phost, MSC_Handle->rw_lun, 0); + + if((error != USBH_BUSY) || + ((int32_t)(HAL_GetTick() - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) + { + MSC_Handle->state = MSC_IDLE; + error = USBH_OK; + + if (MSC_Handle->CmdCompleteCallback != NULL) + { + MSC_Handle->CmdCompleteCallback(USBH_OK); + MSC_Handle->CmdCompleteCallback = NULL; + } + } + break; + + default: + break; + } + return error; +} + + +/** + * @brief USBH_MSC_SOFProcess + * The function is for SOF state + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} +/** + * @brief USBH_MSC_RdWrProcess + * The function is for managing state machine for MSC I/O Process + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + USBH_StatusTypeDef error = USBH_BUSY ; + USBH_StatusTypeDef scsi_status = USBH_BUSY ; + + /* Switch MSC REQ state machine */ + switch (MSC_Handle->unit[lun].state) + { + + case MSC_READ: + scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, 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; + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + case MSC_WRITE: + scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, 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; +#endif //#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + + case MSC_REQUEST_SENSE: + scsi_status = USBH_MSC_SCSI_RequestSense(phost, lun, &MSC_Handle->unit[lun].sense); + + if( scsi_status == USBH_OK) + { + USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[lun].sense.key); + USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[lun].sense.asc); + USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq); + MSC_Handle->unit[lun].state = MSC_IDLE; + MSC_Handle->unit[lun].error = MSC_ERROR; + error = USBH_FAIL; + } + if( scsi_status == USBH_FAIL) + { + USBH_UsrLog ("MSC Device NOT ready"); + } + else if(scsi_status == USBH_UNRECOVERED_ERROR) + { + MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); +#endif + break; + + default: + break; + + } + return error; +} + + +/** + * @brief USBH_MSC_GetMaxLUN + * The function return the Max LUN supported + * @param phost: Host handle + * @retval logical Unit Number supported + */ +int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->gState == HOST_CLASS) && (MSC_Handle->state == MSC_IDLE)) + { + return MSC_Handle->max_lun; + } + return 0xFF; +} + +/** + * @brief USBH_MSC_UnitIsReady + * The function check whether a LUN is ready + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval Lun status (0: not ready / 1: ready) + */ +uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, + uint8_t lun, + MSC_CmdCompleteCallback callback) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE)) + { + return USBH_FAIL; + } + + MSC_Handle->state = MSC_TEST_UNIT_READY; + MSC_Handle->rw_lun = lun; + MSC_Handle->CmdCompleteCallback = callback; + MSC_Handle->timeout = HAL_GetTick() + MSC_TIMEOUT_FIXED_MS; + + return USBH_MSC_SCSI_TestUnitReady(phost, lun); +} + +/** + * @brief USBH_MSC_GetLUNInfo + * The function return a LUN information + * @param phost: Host handle + * @param lun: logical Unit Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + if(phost->gState == HOST_CLASS) + { + USBH_memcpy(info,&MSC_Handle->unit[lun], sizeof(MSC_LUNTypeDef)); + return USBH_OK; + } + else + { + return USBH_FAIL; + } +} + +/** + * @brief USBH_MSC_Read + * The function performs a Read operation + * @param phost: Host handle + * @param lun: logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to read + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint32_t length, + MSC_CmdCompleteCallback callback) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE) || + (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; + MSC_Handle->CmdCompleteCallback = callback; + MSC_Handle->timeout = HAL_GetTick() + MSC_TIMEOUT_FIXED_MS; + + return USBH_MSC_SCSI_Read(phost, + lun, + address, + length); +} + + + +/** + * @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 + */ +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED +USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint32_t length, + MSC_CmdCompleteCallback callback) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE) || + (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; + MSC_Handle->CmdCompleteCallback = callback; + MSC_Handle->timeout = HAL_GetTick() + MSC_TIMEOUT_FIXED_MS; + + return USBH_MSC_SCSI_Write(phost, + lun, + address, + length); +} +#endif //#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + + + +USBH_StatusTypeDef USBH_MSC_StartStopUnit(USBH_HandleTypeDef *phost, + uint8_t lun, + uint8_t startStop, + MSC_CmdCompleteCallback callback) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if ((phost->device.is_connected == 0) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE)) + { + return USBH_FAIL; + } + + MSC_Handle->state = MSC_START_STOP; + MSC_Handle->rw_lun = lun; + MSC_Handle->timeout = HAL_GetTick() + MSC_TIMEOUT_FIXED_MS; + MSC_Handle->CmdCompleteCallback = callback; + + return USBH_MSC_SCSI_StartStopUnit(phost, + lun, + startStop); +} + + +#endif //#ifdef CONFIG_MASS_STORAGE_ENABLED + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c new file mode 100644 index 0000000..dd48182 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c @@ -0,0 +1,737 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file includes the BOT protocol related functions + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_msc_bot.h" +#include "usbh_msc.h" +#include "downstream_spi.h" +#include "downstream_msc.h" +#include "downstream_statemachine.h" +#include "build_config.h" + + +#ifdef CONFIG_MASS_STORAGE_ENABLED + +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); +void USBH_MSC_BOT_Read_Multipacket_FreePacketCallback(DownstreamPacketTypeDef* freePacket); +void USBH_MSC_BOT_Read_Multipacket_PrepareURB(USBH_HandleTypeDef *phost); +void USBH_MSC_BOT_Write_Multipacket_ReceivePacketCallback(DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength); +void USBH_MSC_BOT_Write_Multipacket_PrepareURB(USBH_HandleTypeDef *phost); + + + +USBH_HandleTypeDef *Callback_MSC_phost; + + +/** + * @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) +{ + if (phost->RequestState == CMD_SEND) + { + 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) +{ + if (phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | + USB_REQ_TYPE_CLASS | + USB_REQ_RECIPIENT_INTERFACE; + + phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; + phost->Control.setup.b.wValue.w = 0; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 1; + } + + return USBH_CtlReq(phost, Maxlun , 1 ); +} + + + +/** + * @brief USBH_MSC_BOT_Init + * The function Initializes the BOT protocol. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost) +{ + + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE; + MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG; + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; + + return USBH_OK; +} + + + +/** + * @brief USBH_MSC_BOT_Process + * The function handle the BOT protocol. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) +{ + USBH_StatusTypeDef status = USBH_BUSY; + USBH_StatusTypeDef error = USBH_BUSY; + BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + uint32_t partialTransferLength; + 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; + } + + } + else if(URB_Status == USBH_URB_NOTREADY) + { + /* Re-send CBW */ + MSC_Handle->hbot.state = BOT_SEND_CBW; + } + else if(URB_Status == USBH_URB_STALL) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + } + break; + + case BOT_DATA_IN: + if (MSC_Handle->hbot.pbuf != NULL) + { + //Simple single-buffer operation + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; + MSC_Handle->hbot.this_URB_size = MIN(MSC_Handle->hbot.cbw.field.DataTransferLength, + MSC_Handle->InEpSize); + USBH_BulkReceiveData (phost, + MSC_Handle->hbot.pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->InPipe); + } + else + { + //Asynchronous multi-packet operation: get first packet + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT_FREE_PACKET; + Callback_MSC_phost = phost; + if (Downstream_GetFreePacket(USBH_MSC_BOT_Read_Multipacket_FreePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + } + } + break; + + case BOT_DATA_IN_WAIT_FREE_PACKET: + break; + + case BOT_DATA_IN_WAIT: + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); + + if (URB_Status == USBH_URB_DONE) + { + if (USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != MSC_Handle->hbot.this_URB_size) + { + while(1); + } + + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size; + + if (MSC_Handle->hbot.pbuf != NULL) + { + //Simple single-buffer operation: everything must fit in one URB + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + else + { + //Asynchronous multi-packet operation + MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size; + MSC_Handle->hbot.bot_packet_pbuf += MSC_Handle->hbot.this_URB_size; + + if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0) + { + //End of reception: dispatch last packet + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + Downstream_MSC_PutStreamDataPacket(MSC_Handle->hbot.bot_packet, + (BOT_PAGE_LENGTH - MSC_Handle->hbot.bot_packet_bytes_remaining)); + } + else + { + //Still more data to receive +// if (MSC_Handle->hbot.bot_packet_bytes_remaining == 0) +// { + //Dispatch current bot_packet, then get a new one + if (Downstream_MSC_PutStreamDataPacket(MSC_Handle->hbot.bot_packet, + BOT_PAGE_LENGTH) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + break; + } + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT_FREE_PACKET; + if (Downstream_GetFreePacket(USBH_MSC_BOT_Read_Multipacket_FreePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + break; + } +// } +// else +// { +// //Continue filling the current bot_packet +// USBH_MSC_BOT_Read_Multipacket_PrepareURB(phost); +// } + } + } + } + + 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.*/ + } + break; + + case BOT_DATA_OUT: + if (MSC_Handle->hbot.pbuf != NULL) + { + //Simple single-buffer operation + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; + MSC_Handle->hbot.this_URB_size = MIN(MSC_Handle->hbot.cbw.field.DataTransferLength, + MSC_Handle->OutEpSize); + USBH_BulkSendData (phost, + MSC_Handle->hbot.pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->OutPipe, + 1); + } +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + else + { + //Asynchronous multi-packet operation: get first packet + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT_RECEIVE_PACKET; + Callback_MSC_phost = phost; + if (Downstream_MSC_GetStreamDataPacket(USBH_MSC_BOT_Write_Multipacket_ReceivePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + } + } +#endif + break; + + case BOT_DATA_OUT_WAIT_RECEIVE_PACKET: + break; + + case BOT_DATA_OUT_WAIT: + URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); + + if(URB_Status == USBH_URB_DONE) + { + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size; + + if (MSC_Handle->hbot.pbuf != NULL) + { + //Simple single-buffer operation: everything must fit in one URB + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + else + { + //Asynchronous multi-packet operation + MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size; + MSC_Handle->hbot.bot_packet_pbuf += MSC_Handle->hbot.this_URB_size; + if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0) + { + //End of transmission + Downstream_ReleasePacket(MSC_Handle->hbot.bot_packet); + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + else + { + //Still more data to send + if (MSC_Handle->hbot.bot_packet_bytes_remaining == 0) + { + //Get next bot_packet + Downstream_ReleasePacket(MSC_Handle->hbot.bot_packet); + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT_RECEIVE_PACKET; + if (Downstream_MSC_GetStreamDataPacket(USBH_MSC_BOT_Write_Multipacket_ReceivePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + } + } + else + { + //Continue writing the current bot_packet + USBH_MSC_BOT_Write_Multipacket_PrepareURB(phost); + } + } + } +#endif + } + + else if(URB_Status == USBH_URB_NOTREADY) + { + /* Resend same data */ + if (MSC_Handle->hbot.pbuf != NULL) + { + MSC_Handle->hbot.state = BOT_DATA_OUT; + } +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + else + { + //Increment counters by the amount of data actually transferred during the NAK'd URB + partialTransferLength = USBH_LL_GetLastXferSize(phost, MSC_Handle->OutPipe); + MSC_Handle->hbot.cbw.field.DataTransferLength -= partialTransferLength; + MSC_Handle->hbot.bot_packet_bytes_remaining -= partialTransferLength; + MSC_Handle->hbot.bot_packet_pbuf += partialTransferLength; + + USBH_MSC_BOT_Write_Multipacket_PrepareURB(phost); + } +#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. + */ + } + 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; + } + } + else if(URB_Status == USBH_URB_STALL) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + } + 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; +} + + +void USBH_MSC_BOT_Read_Multipacket_FreePacketCallback(DownstreamPacketTypeDef* freePacket) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + + if (MSC_Handle->hbot.state != BOT_DATA_IN_WAIT_FREE_PACKET) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; + MSC_Handle->hbot.bot_packet = freePacket; + MSC_Handle->hbot.bot_packet_pbuf = freePacket->Data; + MSC_Handle->hbot.bot_packet_bytes_remaining = BOT_PAGE_LENGTH; + USBH_MSC_BOT_Read_Multipacket_PrepareURB(Callback_MSC_phost); +} + + +void USBH_MSC_BOT_Read_Multipacket_PrepareURB(USBH_HandleTypeDef *phost) +{ + uint32_t temp_URB_size; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + temp_URB_size = MSC_Handle->hbot.cbw.field.DataTransferLength; + if (temp_URB_size > MSC_Handle->hbot.bot_packet_bytes_remaining) + { + temp_URB_size = MSC_Handle->hbot.bot_packet_bytes_remaining; + } +// if (temp_URB_size > MSC_Handle->InEpSize) +// { +// temp_URB_size = MSC_Handle->InEpSize; +// } + MSC_Handle->hbot.this_URB_size = (uint16_t)temp_URB_size; + + USBH_BulkReceiveData(phost, + MSC_Handle->hbot.bot_packet_pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->InPipe); +} + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED +void USBH_MSC_BOT_Write_Multipacket_ReceivePacketCallback(DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + + if (MSC_Handle->hbot.state != BOT_DATA_OUT_WAIT_RECEIVE_PACKET) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; + MSC_Handle->hbot.bot_packet = receivedPacket; + MSC_Handle->hbot.bot_packet_pbuf = receivedPacket->Data; + MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength; + USBH_MSC_BOT_Write_Multipacket_PrepareURB(Callback_MSC_phost); +} + + +void USBH_MSC_BOT_Write_Multipacket_PrepareURB(USBH_HandleTypeDef *phost) +{ + uint32_t temp_URB_size; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + temp_URB_size = MSC_Handle->hbot.cbw.field.DataTransferLength; + if (temp_URB_size > MSC_Handle->hbot.bot_packet_bytes_remaining) + { + temp_URB_size = MSC_Handle->hbot.bot_packet_bytes_remaining; + } + if (temp_URB_size > MSC_Handle->OutEpSize)// * 4) //Some silicon has a buggy host fifo, so we write single packets only :( + { + temp_URB_size = MSC_Handle->OutEpSize;// * 4; + } + MSC_Handle->hbot.this_URB_size = (uint16_t)temp_URB_size; + + USBH_BulkSendData (phost, + MSC_Handle->hbot.bot_packet_pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->OutPipe, + 1); +} +#endif + +/** + * @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) +{ + UNUSED(lun); + USBH_StatusTypeDef status = USBH_FAIL; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch (dir) + { + case BOT_DIR_IN : + /* send ClrFeture on Bulk IN endpoint */ + status = USBH_ClrFeature(phost, MSC_Handle->InEp); + + break; + + case BOT_DIR_OUT : + /*send ClrFeature on Bulk OUT endpoint */ + status = USBH_ClrFeature(phost, MSC_Handle->OutEp); + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_MSC_BOT_DecodeCSW + * This function decodes the CSW received by the device and updates the + * same to upper layer. + * @param phost: Host handle + * @retval USBH Status + * @notes + * Refer to USB Mass-Storage Class : BOT (www.usb.org) + * 6.3.1 Valid CSW Conditions : + * The host shall consider the CSW valid when: + * 1. dCSWSignature is equal to 53425355h + * 2. the CSW is 13 (Dh) bytes in length, + * 3. dCSWTag matches the dCBWTag from the corresponding CBW. + */ + +static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED; + + /*Checking if the transfer length is different than 13*/ + if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH) + { + /*(4) Hi > Dn (Host expects to receive data from the device, + Device intends to transfer no data) + (5) Hi > Di (Host expects to receive data from the device, + Device intends to send data to the host) + (9) Ho > Dn (Host expects to send data to the device, + Device intends to transfer no data) + (11) Ho > Do (Host expects to send data to the device, + Device intends to receive data from the host)*/ + + + status = BOT_CSW_PHASE_ERROR; + } + else + { /* CSW length is Correct */ + + /* Check validity of the CSW Signature and CSWStatus */ + if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE) + {/* Check Condition 1. dCSWSignature is equal to 53425355h */ + + if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag) + { + /* Check Condition 3. dCSWTag matches the dCBWTag from the + corresponding CBW */ + + if(MSC_Handle->hbot.csw.field.Status == 0) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + + Hn Host expects no data transfers + Hi Host expects to receive data from the device + Ho Host expects to send data to the device + + Dn Device intends to transfer no data + Di Device intends to send data to the host + Do Device intends to receive data from the host + + Section 6.7 + (1) Hn = Dn (Host expects no data transfers, + Device intends to transfer no data) + (6) Hi = Di (Host expects to receive data from the device, + Device intends to send data to the host) + (12) Ho = Do (Host expects to send data to the device, + Device intends to receive data from the host) + + */ + + status = BOT_CSW_CMD_PASSED; + } + else if(MSC_Handle->hbot.csw.field.Status == 1) + { + status = BOT_CSW_CMD_FAILED; + } + + else if(MSC_Handle->hbot.csw.field.Status == 2) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + Section 6.7 + (2) Hn < Di ( Host expects no data transfers, + Device intends to send data to the host) + (3) Hn < Do ( Host expects no data transfers, + Device intends to receive data from the host) + (7) Hi < Di ( Host expects to receive data from the device, + Device intends to send data to the host) + (8) Hi <> Do ( Host expects to receive data from the device, + Device intends to receive data from the host) + (10) Ho <> Di (Host expects to send data to the device, + Di Device intends to send data to the host) + (13) Ho < Do (Host expects to send data to the device, + Device intends to receive data from the host) + */ + + status = BOT_CSW_PHASE_ERROR; + } + } /* CSW Tag Matching is Checked */ + } /* CSW Signature Correct Checking */ + else + { + /* If the CSW Signature is not valid, We sall return the Phase Error to + Upper Layers for Reset Recovery */ + + status = BOT_CSW_PHASE_ERROR; + } + } /* CSW Length Check*/ + + return status; +} + +#endif //#ifdef CONFIG_MASS_STORAGE_ENABLED + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c new file mode 100644 index 0000000..8028139 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c @@ -0,0 +1,473 @@ +/** + ****************************************************************************** + * @file usbh_msc_scsi.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements the SCSI commands + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.h" +#include "build_config.h" + + +#ifdef CONFIG_MASS_STORAGE_ENABLED + +/** @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) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if (MSC_Handle->hbot.cmd_state == 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; + } + + return USBH_MSC_BOT_Process(phost, lun); +} + +/** + * @brief USBH_MSC_SCSI_ReadCapacity + * Issue Read Capacity command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the capacity structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_CapacityTypeDef *capacity) +{ + USBH_StatusTypeDef error = USBH_BUSY ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch(MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + + if(error == USBH_OK) + { + /*assign the capacity*/ + capacity->block_nbr = (MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\ + (MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24)) + 1; //block_nbr = logical address of last block + 1 + + /*assign the page length*/ + capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8); + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_Inquiry + * Issue Inquiry command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the inquiry structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_StdInquiryDataTypeDef *inquiry) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + switch(MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY; + MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); + MSC_Handle->hbot.cbw.field.CB[2] = 0; + MSC_Handle->hbot.cbw.field.CB[3] = 0; + MSC_Handle->hbot.cbw.field.CB[4] = 0x24; + MSC_Handle->hbot.cbw.field.CB[5] = 0; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + + if(error == USBH_OK) + { + USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef)); + /*assign Inquiry Data */ + inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F; + inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5; + inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80; + USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8); + USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16); + USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4); + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_RequestSense + * Issue RequestSense command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param capacity: pointer to the sense data structure + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, + uint8_t lun, + SCSI_SenseTypeDef *sense_data) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch(MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); + MSC_Handle->hbot.cbw.field.CB[2] = 0; + MSC_Handle->hbot.cbw.field.CB[3] = 0; + MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE; + MSC_Handle->hbot.cbw.field.CB[5] = 0; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + + error = USBH_MSC_BOT_Process(phost, lun); + if (error == USBH_OK) + { + sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F; + sense_data->asc = MSC_Handle->hbot.pbuf[12]; + sense_data->ascq = MSC_Handle->hbot.pbuf[13]; + } + break; + + default: + break; + } + + return error; +} + +/** + * @brief USBH_MSC_SCSI_Write + * Issue write10 command. + * @param phost: Host handle + * @param lun: Logical Unit Number + * @param address: sector address + * @param pbuf: pointer to data + * @param length: number of sector to write + * @retval USBH Status + */ +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED +USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, + uint8_t lun, + uint32_t address, + uint32_t length) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch(MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[lun].capacity.block_size; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10; + + /*logical block address*/ + MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]); + MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]); + MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); + MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); + + /*Transfer length */ + MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; + MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = NULL; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = USBH_MSC_BOT_Process(phost, lun); + break; + + default: + break; + } + + return error; +} +#endif + +/** + * @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, + uint32_t length) +{ + USBH_StatusTypeDef error = USBH_FAIL ; + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + switch(MSC_Handle->hbot.cmd_state) + { + case BOT_CMD_SEND: + /*Prepare the CBW and relevant fields*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[lun].capacity.block_size;; + MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; + MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; + + USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); + MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10; + + /*logical block address*/ + MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]); + MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]); + MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); + MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); + + /*Transfer length */ + MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; + MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + MSC_Handle->hbot.pbuf = NULL; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = USBH_MSC_BOT_Process(phost, lun); + break; + + default: + break; + } + + return error; +} + + +USBH_StatusTypeDef USBH_MSC_SCSI_StartStopUnit(USBH_HandleTypeDef *phost, + uint8_t lun, + uint8_t startStop) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + if (MSC_Handle->hbot.cmd_state == BOT_CMD_SEND) + { + /*Prepare the CBW and relevent field*/ + MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_START_STOP_UNIT; + 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_START_STOP_UNIT; + MSC_Handle->hbot.cbw.field.CB[4] = 0x02 | (startStop & 0x01); //LOEJ = 1, START = 0 for eject, START = 1 for load + + MSC_Handle->hbot.state = BOT_SEND_CBW; + MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; + } + + return USBH_MSC_BOT_Process(phost, lun); +} + + +#endif //#ifdef CONFIG_MASS_STORAGE_ENABLED + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_core.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_core.h new file mode 100644 index 0000000..c9d913d --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_core.h @@ -0,0 +1,170 @@ +/** + ****************************************************************************** + * @file usbh_core.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_core.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_CORE_H +#define __USBH_CORE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_config.h" +#include "usbh_def.h" +#include "usbh_ioreq.h" +#include "usbh_pipes.h" +#include "usbh_ctlreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CORE + * @brief This file is the Header file for usbh_core.c + * @{ + */ + + +/** @defgroup USBH_CORE_Exported_Defines + * @{ + */ + +/** + * @} + */ +#define HOST_USER_SELECT_CONFIGURATION 1 +#define HOST_USER_CLASS_ACTIVE 2 +#define HOST_USER_CLASS_SELECTED 3 +#define HOST_USER_CONNECTION 4 +#define HOST_USER_DISCONNECTION 5 +#define HOST_USER_UNRECOVERED_ERROR 6 +#define HOST_USER_CLASS_FAILED 7 + +/** + * @} + */ + + + +/** @defgroup USBH_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBH_CORE_Exported_FunctionsPrototype + * @{ + */ + + +USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id); +USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass); +USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface); +uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, + uint8_t Class, + uint8_t SubClass, + uint8_t Protocol); +uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost); + +uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, + uint8_t interface_number, + uint8_t alt_settings); + +USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_Process (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost); + +/* USBH Low Level Driver */ +USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Start (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost); + +USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_PortEnabled (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost); +USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost); +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost); +uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t ); +USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t ); + +USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, uint8_t, uint8_t, uint8_t, uint8_t , uint8_t, uint16_t ); +USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t ); +USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, uint8_t, uint8_t,uint8_t, uint8_t, uint8_t*, uint16_t, uint8_t ); +USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t ); +#if (USBH_USE_OS == 1) +USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost); +#endif +USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t , uint8_t ); +uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t ); + +/* USBH Time base */ +void USBH_Delay (uint32_t Delay); +void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t ); +void USBH_LL_IncTimer (USBH_HandleTypeDef *phost); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CORE_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h new file mode 100644 index 0000000..1284a55 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ctlreq.h @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_ctlreq.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_CTLREQ_H +#define __USBH_CTLREQ_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CTLREQ + * @brief This file is the + * @{ + */ + + +/** @defgroup USBH_CTLREQ_Exported_Defines + * @{ + */ +/*Standard Feature Selector for clear feature command*/ +#define FEATURE_SELECTOR_ENDPOINT 0X00 +#define FEATURE_SELECTOR_DEVICE 0X01 + + +#define INTERFACE_DESC_TYPE 0x04 +#define ENDPOINT_DESC_TYPE 0x05 +#define INTERFACE_DESC_SIZE 0x09 + +/** + * @} + */ + + +/** @defgroup USBH_CTLREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CTLREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_CTLREQ_Exported_Variables + * @{ + */ +//extern uint8_t USBH_CfgDesc[512]; +/** + * @} + */ + +/** @defgroup USBH_CTLREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length); + +USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, + uint8_t req_type, + uint16_t type_idx, + uint16_t value, + uint8_t* buff, + uint16_t length ); + +USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, + uint16_t length); + +USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length); + +USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, + uint16_t configuration_value); + +USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, + uint16_t length); + +USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, + uint8_t DeviceAddress); + +USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, + uint8_t ep_num, uint8_t altSetting); + +USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, + uint8_t ep_num); + +USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, + uint16_t *ptr); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_CTLREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_def.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_def.h new file mode 100644 index 0000000..93521e2 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_def.h @@ -0,0 +1,503 @@ +/** + ****************************************************************************** + * @file usbh_def.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Definitions used in the USB host library + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef USBH_DEF_H +#define USBH_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_config.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_DEF + * @brief This file is includes USB descriptors + * @{ + */ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + + +#define ValBit(VAR,POS) (VAR & (1 << POS)) +#define SetBit(VAR,POS) (VAR |= (1 << POS)) +#define ClrBit(VAR,POS) (VAR &= ((1 << POS)^255)) + +#define LE16(addr) (((uint16_t)(*((uint8_t *)(addr))))\ + + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) + +#define LE16S(addr) (uint16_t)(LE16((addr))) + +#define LE32(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \ + (((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \ + (((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16) + \ + (((uint32_t)(*(((uint8_t *)(addr)) + 3))) << 24))) + +#define LE64(addr) ((((uint64_t)(*(((uint8_t *)(addr)) + 0))) + \ + (((uint64_t)(*(((uint8_t *)(addr)) + 1))) << 8) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 2))) << 16) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 3))) << 24) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 4))) << 32) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 5))) << 40) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 6))) << 48) +\ + (((uint64_t)(*(((uint8_t *)(addr)) + 7))) << 56))) + + +#define LE24(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \ + (((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \ + (((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16))) + + +#define LE32S(addr) (int32_t)(LE32((addr))) + + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + +#define USB_LEN_DESC_HDR 0x02 +#define USB_LEN_DEV_DESC 0x12 +#define USB_LEN_CFG_DESC 0x09 +#define USB_LEN_IF_DESC 0x09 +#define USB_LEN_EP_DESC 0x07 +#define USB_LEN_OTG_DESC 0x03 +#define USB_LEN_SETUP_PKT 0x08 + +/* bmRequestType :D7 Data Phase Transfer Direction */ +#define USB_REQ_DIR_MASK 0x80 +#define USB_H2D 0x00 +#define USB_D2H 0x80 + +/* bmRequestType D6..5 Type */ +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_RESERVED 0x60 + +/* bmRequestType D4..0 Recipient */ +#define USB_REQ_RECIPIENT_DEVICE 0x00 +#define USB_REQ_RECIPIENT_INTERFACE 0x01 +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 +#define USB_REQ_RECIPIENT_OTHER 0x03 + +/* Table 9-4. Standard Request Codes */ +/* bRequest , Value */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +/* Table 9-5. Descriptor Types of USB Specifications */ +#define USB_DESC_TYPE_DEVICE 1 +#define USB_DESC_TYPE_CONFIGURATION 2 +#define USB_DESC_TYPE_STRING 3 +#define USB_DESC_TYPE_INTERFACE 4 +#define USB_DESC_TYPE_ENDPOINT 5 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 +#define USB_DESC_TYPE_INTERFACE_POWER 8 +#define USB_DESC_TYPE_HID 0x21 +#define USB_DESC_TYPE_HID_REPORT 0x22 + + +#define USB_DEVICE_DESC_SIZE 18 +#define USB_CONFIGURATION_DESC_SIZE 9 +#define USB_HID_DESC_SIZE 9 +#define USB_INTERFACE_DESC_SIZE 9 +#define USB_ENDPOINT_DESC_SIZE 7 + +/* Descriptor Type and Descriptor Index */ +/* Use the following values when calling the function USBH_GetDescriptor */ +#define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00) +#define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00) +#define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00) +#define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) +#define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) +#define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00) +#define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00) +#define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00) +#define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00) +#define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00) + + +#define USB_EP_TYPE_CTRL 0x00 +#define USB_EP_TYPE_ISOC 0x01 +#define USB_EP_TYPE_BULK 0x02 +#define USB_EP_TYPE_INTR 0x03 + +#define USB_EP_DIR_OUT 0x00 +#define USB_EP_DIR_IN 0x80 +#define USB_EP_DIR_MSK 0x80 + +#ifndef USBH_MAX_PIPES_NBR + #define USBH_MAX_PIPES_NBR 15 +#endif /* USBH_MAX_PIPES_NBR */ + +#define USBH_DEVICE_ADDRESS_DEFAULT 0 +#define USBH_MAX_ERROR_COUNT 10 +#define USBH_DEVICE_ADDRESS 1 + +#define USBH_CTRL_TRANSACTION_TIMEOUT_MS 200 + + +/** + * @} + */ + + +#define USBH_CONFIGURATION_DESCRIPTOR_SIZE (USB_CONFIGURATION_DESC_SIZE \ + + USB_INTERFACE_DESC_SIZE\ + + (USBH_MAX_NUM_ENDPOINTS * USB_ENDPOINT_DESC_SIZE)) + + +#define CONFIG_DESC_wTOTAL_LENGTH (ConfigurationDescriptorData.ConfigDescfield.\ + ConfigurationDescriptor.wTotalLength) + + +typedef union +{ + uint16_t w; + struct BW + { + uint8_t msb; + uint8_t lsb; + } + bw; +} +uint16_t_uint8_t; + + +typedef union _USB_Setup +{ + uint32_t d8[2]; + + struct _SetupPkt_Struc + { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t_uint8_t wValue; + uint16_t_uint8_t wIndex; + uint16_t_uint8_t wLength; + } b; +} +USB_Setup_TypeDef; + +typedef struct _DescHeader +{ + uint8_t bLength; + uint8_t bDescriptorType; +} +USBH_DescHeader_t; + +typedef struct _DeviceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; /* USB Specification Number which device complies too */ + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + /* If equal to Zero, each interface specifies its own class + code if equal to 0xFF, the class code is vendor specified. + Otherwise field is valid Class Code.*/ + uint8_t bMaxPacketSize; + uint16_t idVendor; /* Vendor ID (Assigned by USB Org) */ + uint16_t idProduct; /* Product ID (Assigned by Manufacturer) */ + uint16_t bcdDevice; /* Device Release Number */ + uint8_t iManufacturer; /* Index of Manufacturer String Descriptor */ + uint8_t iProduct; /* Index of Product String Descriptor */ + uint8_t iSerialNumber; /* Index of Serial Number String Descriptor */ + uint8_t bNumConfigurations; /* Number of Possible Configurations */ +} +USBH_DevDescTypeDef; + +typedef struct _EndpointDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; /* indicates what endpoint this descriptor is describing */ + uint8_t bmAttributes; /* specifies the transfer type. */ + uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /* is used to specify the polling interval of certain transfers. */ +} +USBH_EpDescTypeDef; + +typedef struct _InterfaceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; /* Value used to select alternative setting */ + uint8_t bNumEndpoints; /* Number of Endpoints used for this interface */ + uint8_t bInterfaceClass; /* Class Code (Assigned by USB Org) */ + uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */ + uint8_t bInterfaceProtocol; /* Protocol Code */ + uint8_t iInterface; /* Index of String Descriptor Describing this interface */ + USBH_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS]; +} +USBH_InterfaceDescTypeDef; + + +typedef struct _ConfigurationDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; /* Total Length of Data Returned */ + uint8_t bNumInterfaces; /* Number of Interfaces */ + uint8_t bConfigurationValue; /* Value to use as an argument to select this configuration*/ + uint8_t iConfiguration; /*Index of String Descriptor Describing this configuration */ + uint8_t bmAttributes; /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/ + uint8_t bMaxPower; /*Maximum Power Consumption */ + USBH_InterfaceDescTypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES]; +} +USBH_CfgDescTypeDef; + + +/* Following USB Host status */ +typedef enum +{ + USBH_OK = 0, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_ERROR_SPEED_UNKNOWN, +}USBH_StatusTypeDef; + + +/** @defgroup USBH_CORE_Exported_Types + * @{ + */ + +typedef enum +{ + USBH_SPEED_HIGH = 0, + USBH_SPEED_FULL = 1, + USBH_SPEED_LOW = 2, + +}USBH_SpeedTypeDef; + +/* Following states are used for gState */ +typedef enum +{ + HOST_IDLE =0, + HOST_DEV_WAIT_FOR_ATTACHMENT, + HOST_DEV_ATTACHED, + HOST_DEV_DISCONNECTED, + HOST_DETECT_DEVICE_SPEED, + HOST_ENUMERATION, + HOST_CLASS_REQUEST, + HOST_INPUT, + HOST_SET_CONFIGURATION, + HOST_CHECK_CLASS, + HOST_CLASS, + HOST_SUSPENDED, + HOST_ABORT_STATE, +}HOST_StateTypeDef; + +/* Following states are used for EnumerationState */ +typedef enum +{ + ENUM_IDLE = 0, + ENUM_GET_FULL_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_FULL_CFG_DESC, + ENUM_GET_MFC_STRING_DESC, + ENUM_GET_PRODUCT_STRING_DESC, + ENUM_GET_SERIALNUM_STRING_DESC, +} ENUM_StateTypeDef; + +/* Following states are used for CtrlXferStateMachine */ +typedef enum +{ + CTRL_IDLE =0, + CTRL_SETUP, + CTRL_SETUP_WAIT, + CTRL_DATA_IN, + CTRL_DATA_IN_WAIT, + CTRL_DATA_OUT, + CTRL_DATA_OUT_WAIT, + CTRL_STATUS_IN, + CTRL_STATUS_IN_WAIT, + CTRL_STATUS_OUT, + CTRL_STATUS_OUT_WAIT, + CTRL_ERROR, + CTRL_STALLED, + CTRL_COMPLETE +}CTRL_StateTypeDef; + + +/* Following states are used for RequestState */ +typedef enum +{ + CMD_IDLE =0, + CMD_SEND, + CMD_WAIT +} CMD_StateTypeDef; + +typedef enum { + USBH_URB_IDLE = 0, + USBH_URB_DONE, + USBH_URB_NOTREADY, + USBH_URB_NYET, + USBH_URB_ERROR, + USBH_URB_STALL +}USBH_URBStateTypeDef; + +typedef enum +{ + USBH_PORT_EVENT = 1, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +} +USBH_OSEventTypeDef; + +/* Control request structure */ +typedef struct +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t pipe_size; + uint8_t *buff; + uint32_t timer; + uint16_t length; + USB_Setup_TypeDef setup; + CTRL_StateTypeDef state; + uint8_t errorcount; + +} USBH_CtrlTypeDef; + +/* Attached device structure */ +typedef struct +{ +#if (USBH_KEEP_CFG_DESCRIPTOR == 1) + uint8_t CfgDesc_Raw[USBH_MAX_SIZE_CONFIGURATION]; +#endif + uint8_t Data[USBH_MAX_DATA_BUFFER]; + uint8_t address; + uint8_t speed; + __IO uint8_t is_connected; + uint8_t current_interface; + USBH_DevDescTypeDef DevDesc; + USBH_CfgDescTypeDef CfgDesc; + +}USBH_DeviceTypeDef; + +struct _USBH_HandleTypeDef; + +/* USB Host Class structure */ +typedef struct +{ + const char *Name; + uint8_t ClassCode; + USBH_StatusTypeDef (*Init) (struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef (*DeInit) (struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef (*Requests) (struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef (*BgndProcess) (struct _USBH_HandleTypeDef *phost); + USBH_StatusTypeDef (*SOFProcess) (struct _USBH_HandleTypeDef *phost); + void* pData; +} USBH_ClassTypeDef; + + + +#define HOST_PIPE_COUNT 15 + + +/* USB Host handle structure */ +typedef struct _USBH_HandleTypeDef +{ + __IO HOST_StateTypeDef gState; /* Host State Machine Value */ + ENUM_StateTypeDef EnumState; /* Enumeration state Machine */ + CMD_StateTypeDef RequestState; + USBH_CtrlTypeDef Control; + USBH_DeviceTypeDef device; + USBH_ClassTypeDef* pClass[USBH_MAX_NUM_SUPPORTED_CLASS]; + USBH_ClassTypeDef* pActiveClass; + uint32_t ClassNumber; + uint32_t Pipes[HOST_PIPE_COUNT]; + __IO uint32_t Timer; + uint8_t id; + void* pData; + void (* pUser )(struct _USBH_HandleTypeDef *pHandle, uint8_t id); + +#if (USBH_USE_OS == 1) + osMessageQId os_event; + osThreadId thread; +#endif + +} USBH_HandleTypeDef; + + +#if defined ( __GNUC__ ) + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_DEF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h new file mode 100644 index 0000000..ab9029a --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_ioreq.h @@ -0,0 +1,168 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_ioreq.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_IOREQ_H +#define __USBH_IOREQ_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_config.h" +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file is the header file for usbh_ioreq.c + * @{ + */ + + +/** @defgroup USBH_IOREQ_Exported_Defines + * @{ + */ + +#define USBH_PID_SETUP 0 +#define USBH_PID_DATA 1 + +#define USBH_EP_CONTROL 0 +#define USBH_EP_ISO 1 +#define USBH_EP_BULK 2 +#define USBH_EP_INTERRUPT 3 + +#define USBH_SETUP_PKT_SIZE 8 +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_IOREQ_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t hc_num); + +USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t hc_num, + uint8_t do_ping ); + +USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t hc_num); + +USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t hc_num); + +USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t hc_num, + uint8_t do_ping ); + +USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + +USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t hc_num); + + +USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t hc_num); + + +USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t hc_num); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_IOREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h new file mode 100644 index 0000000..16aa438 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc/usbh_pipes.h @@ -0,0 +1,131 @@ +/** + ****************************************************************************** + * @file usbh_pipes.h + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief Header file for usbh_pipes.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_PIPES_H +#define __USBH_PIPES_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_PIPES + * @brief This file is the header file for usbh_pipes.c + * @{ + */ + +/** @defgroup USBH_PIPES_Exported_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Exported_FunctionsPrototype + * @{ + */ + +USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); + +USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num); + +uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, + uint8_t ep_addr); + +USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, + uint8_t idx); + + + + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_PIPES_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_conf_template.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_conf_template.c new file mode 100644 index 0000000..ee63c80 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_conf_template.c @@ -0,0 +1,271 @@ +/** + ****************************************************************************** + * @file usb_bsp.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements the board support package for the USB host library + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_core.h" + +/** + * @brief USBH_LL_Init + * Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_DeInit + * De-Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Start + * Start the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_Stop + * Stop the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetSpeed + * Return the USB Host Speed from the Low Level Driver. + * @param phost: Host handle + * @retval USBH Speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + + return speed; +} + +/** + * @brief USBH_LL_ResetPort + * Reset the Host Port of the Low Level Driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetLastXferSize + * Return the last transferred packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet Size + */ +uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return 0; +} + +/** + * @brief USBH_LL_OpenPipe + * Open a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint Number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint Type + * @param mps: Endpoint Max Packet Size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_ClosePipe + * Close a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return USBH_OK; +} + +/** + * @brief USBH_LL_SubmitURB + * Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochronous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping ) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetURBState + * Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return USBH_URB_IDLE; +} + +/** + * @brief USBH_LL_DriverVBUS + * Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_SetToggle + * Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param pipe_num: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetToggle + * Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + + + return toggle; +} +/** + * @brief USBH_Delay + * Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay (uint32_t Delay) +{ + +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c new file mode 100644 index 0000000..7235146 --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c @@ -0,0 +1,962 @@ +/** + ****************************************************************************** + * @file usbh_core.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements the functions for the core state machine process + * the enumeration and the control transfer process + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_core.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE + * @{ + */ + +/** @defgroup USBH_CORE + * @brief This file handles the basic enumeration when a device is connected + * to the host. + * @{ + */ + + +/** @defgroup USBH_CORE_Private_Defines + * @{ + */ +#define USBH_ADDRESS_DEFAULT 0 +#define USBH_ADDRESS_ASSIGNED 1 +#define USBH_MPS_DEFAULT 0x40 + +#define USBH_ATTACH_DELAY_MS 200 +#define USBH_DETACH_DELAY_MS 500 + +/** + * @} + */ + +/** @defgroup USBH_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_CORE_Private_Functions + * @{ + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost); +static void USBH_HandleSof (USBH_HandleTypeDef *phost); +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost); + +#if (USBH_USE_OS == 1) +static void USBH_Process_OS(void const * argument); +#endif + +/** + * @brief HCD_Init + * Initialize the HOST Core. + * @param phost: Host Handle + * @param pUsrFunc: User Callback + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id) +{ + /* Check whether the USB Host handle is valid */ + if(phost == NULL) + { + USBH_ErrLog("Invalid Host handle"); + return USBH_FAIL; + } + + /* Set DRiver ID */ + phost->id = id; + + /* Unlink class*/ + phost->pActiveClass = NULL; + phost->ClassNumber = 0; + + /* Restore default states and prepare EP0 */ + DeInitStateMachine(phost); + + /* Assign User process */ + if(pUsrFunc != NULL) + { + phost->pUser = pUsrFunc; + } + +#if (USBH_USE_OS == 1) + + /* Create USB Host Queue */ + osMessageQDef(USBH_Queue, 10, uint16_t); + phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); + + /*Create USB Host Task */ +#if defined (USBH_PROCESS_STACK_SIZE) + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, USBH_PROCESS_STACK_SIZE); +#else + osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); +#endif + phost->thread = osThreadCreate (osThread(USBH_Thread), phost); +#endif + + /* Initialize low level driver */ + USBH_LL_Init(phost); + return USBH_OK; +} + +/** + * @brief HCD_Init + * De-Initialize the Host portion of the driver. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost) +{ + DeInitStateMachine(phost); + + if(phost->pData != NULL) + { + phost->pActiveClass->pData = NULL; + USBH_LL_Stop(phost); + } + + USBH_LL_DeInit(phost); + + return USBH_OK; +} + +/** + * @brief DeInitStateMachine + * De-Initialize the Host state machine. + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost) +{ + uint32_t i = 0; + + /* Clear Pipes flags*/ + for ( ; i < USBH_MAX_PIPES_NBR; i++) + { + phost->Pipes[i] = 0; + } + + for(i = 0; i< USBH_MAX_DATA_BUFFER; i++) + { + phost->device.Data[i] = 0; + } + + phost->gState = HOST_IDLE; + phost->EnumState = ENUM_IDLE; + phost->RequestState = CMD_SEND; + phost->Timer = 0; + + phost->Control.state = CTRL_SETUP; + phost->Control.pipe_size = USBH_MPS_DEFAULT; + phost->Control.errorcount = 0; + + phost->device.address = USBH_ADDRESS_DEFAULT; + phost->device.speed = USBH_SPEED_FULL; + phost->device.is_connected = 0; + + return USBH_OK; +} + +/** + * @brief USBH_RegisterClass + * Link class driver to Host Core. + * @param phost : Host Handle + * @param pclass: Class handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(pclass != 0) + { + if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS) + { + /* link the class to the USB Host handle */ + phost->pClass[phost->ClassNumber++] = pclass; + status = USBH_OK; + } + else + { + USBH_ErrLog("Max Class Number reached"); + status = USBH_FAIL; + } + } + else + { + USBH_ErrLog("Invalid Class handle"); + status = USBH_FAIL; + } + + return status; +} + +/** + * @brief USBH_SelectInterface + * Select current interface. + * @param phost: Host Handle + * @param interface: Interface number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface) +{ + USBH_StatusTypeDef status = USBH_OK; + + if(interface < phost->device.CfgDesc.bNumInterfaces) + { + phost->device.current_interface = interface; + USBH_UsrLog ("Switching to Interface (#%d)", interface); + USBH_UsrLog ("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass ); + USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass ); + USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol ); + } + else + { + USBH_ErrLog ("Cannot Select This Interface."); + status = USBH_FAIL; + } + return status; +} + +/** + * @brief USBH_GetActiveClass + * Return Device Class. + * @param phost: Host Handle + * @param interface: Interface index + * @retval Class Code + */ +uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost) +{ + return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass); +} +/** + * @brief USBH_FindInterface + * Find the interface index for a specific class. + * @param phost: Host Handle + * @param Class: Class code + * @param SubClass: SubClass code + * @param Protocol: Protocol code + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&& + ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&& + ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF))) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_FindInterfaceIndex + * Find the interface index for a specific class interface and alternate setting number. + * @param phost: Host Handle + * @param interface_number: interface number + * @param alt_settings : alternate setting number + * @retval interface index in the configuration structure + * @note : (1)interface index 0xFF means interface index not found + */ +uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_CfgDescTypeDef *pcfg ; + int8_t if_ix = 0; + + pif = (USBH_InterfaceDescTypeDef *)0; + pcfg = &phost->device.CfgDesc; + + while (if_ix < USBH_MAX_NUM_INTERFACES) + { + pif = &pcfg->Itf_Desc[if_ix]; + if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) + { + return if_ix; + } + if_ix++; + } + return 0xFF; +} + +/** + * @brief USBH_Start + * Start the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost) +{ + /* Start the low level driver */ + USBH_LL_Start(phost); + + /* Activate VBUS on the port */ + USBH_LL_DriverVBUS (phost, TRUE); + + return USBH_OK; +} + +/** + * @brief USBH_Stop + * Stop the USB Host Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost) +{ + /* Stop and cleanup the low level driver */ + USBH_LL_Stop(phost); + + /* DeActivate VBUS on the port */ + USBH_LL_DriverVBUS (phost, FALSE); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + return USBH_OK; +} + +/** + * @brief HCD_ReEnumerate + * Perform a new Enumeration phase. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost) +{ + /*Stop Host */ + USBH_Stop(phost); + + /*Device has disconnected, so wait for 200 ms */ + USBH_Delay(200); + + /* Set State machines in default state */ + DeInitStateMachine(phost); + + /* Start again the host */ + USBH_Start(phost); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + return USBH_OK; +} + +/** + * @brief USBH_Process + * Background process of the USB Core. + * @param phost: Host Handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) +{ + __IO USBH_StatusTypeDef status = USBH_FAIL; + uint8_t idx = 0; + + switch (phost->gState) + { + case HOST_IDLE: + + if (phost->device.is_connected) + { + /* Wait for 200 ms after connection */ + phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT; + USBH_Delay(USBH_ATTACH_DELAY_MS); + USBH_LL_ResetPort(phost); +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + } + break; + + case HOST_DEV_WAIT_FOR_ATTACHMENT: + break; + + case HOST_DEV_ATTACHED : + + USBH_UsrLog("USB Device Attached"); + + /* Wait for 100 ms after Reset */ + USBH_Delay(100); + + phost->device.speed = USBH_LL_GetSpeed(phost); + + phost->gState = HOST_ENUMERATION; + + phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00); + phost->Control.pipe_in = USBH_AllocPipe (phost, 0x80); + + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + break; + + case HOST_ENUMERATION: + /* Check for enumeration status */ + if ( USBH_HandleEnum(phost) == USBH_OK) + { + /* The function shall return USBH_OK when full enumeration is complete */ + USBH_UsrLog ("Enumeration done."); + phost->device.current_interface = 0; + if(phost->device.DevDesc.bNumConfigurations == 1) + { + USBH_UsrLog ("This device has only 1 configuration."); + phost->gState = HOST_SET_CONFIGURATION; + + } + else + { + phost->gState = HOST_INPUT; + } + + } + break; + + case HOST_INPUT: + { + /* user callback for end of device basic enumeration */ + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION); + phost->gState = HOST_SET_CONFIGURATION; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + break; + + case HOST_SET_CONFIGURATION: + /* set configuration */ + if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK) + { + phost->gState = HOST_CHECK_CLASS; + USBH_UsrLog ("Default configuration set."); + + } + + break; + + case HOST_CHECK_CLASS: + + if(phost->ClassNumber == 0) + { + USBH_UsrLog ("No Class has been registered."); + } + else + { + phost->pActiveClass = NULL; + + for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++) + { + if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) + { + phost->pActiveClass = phost->pClass[idx]; + } + } + + if(phost->pActiveClass != NULL) + { + if(phost->pActiveClass->Init(phost)== USBH_OK) + { + phost->gState = HOST_CLASS_REQUEST; + USBH_UsrLog ("%s class started.", phost->pActiveClass->Name); + + /* Inform user that a class has been activated */ + phost->pUser(phost, HOST_USER_CLASS_SELECTED); + } + else + { + phost->pUser(phost, HOST_USER_CLASS_FAILED); + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name); + } + } + else + { + phost->pUser(phost, HOST_USER_CLASS_FAILED); + phost->gState = HOST_ABORT_STATE; + USBH_UsrLog ("No registered class for this device."); + } + } + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + break; + + case HOST_CLASS_REQUEST: + /* process class standard control requests state machine */ + if(phost->pActiveClass != NULL) + { + status = phost->pActiveClass->Requests(phost); + + if(status == USBH_OK) + { + phost->gState = HOST_CLASS; + } + } + else + { + phost->gState = HOST_ABORT_STATE; + USBH_ErrLog ("Invalid Class Driver."); + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + + break; + case HOST_CLASS: + /* process class state machine */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->BgndProcess(phost); + } + break; + + case HOST_DEV_DISCONNECTED: + USBH_Delay(USBH_DETACH_DELAY_MS); + DeInitStateMachine(phost); + + /* Re-Initilaize Host for new Enumeration */ + if(phost->pActiveClass != NULL) + { + phost->pActiveClass->DeInit(phost); + phost->pActiveClass = NULL; + } + break; + + case HOST_ABORT_STATE: + default : + break; + } + return USBH_OK; +} + + +/** + * @brief USBH_HandleEnum + * This function includes the complete enumeration process + * @param phost: Host Handle + * @retval USBH_Status + */ +static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) +{ + USBH_StatusTypeDef Status = USBH_BUSY; + + switch (phost->EnumState) + { + case ENUM_IDLE: + /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ + if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) + { + phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; + + phost->EnumState = ENUM_GET_FULL_DEV_DESC; + + /* modify control channels configuration for MaxPacket size */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + } + break; + + case ENUM_GET_FULL_DEV_DESC: + /* Get FULL Device Desc */ + if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK) + { + USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct ); + USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor ); + + phost->EnumState = ENUM_SET_ADDR; + + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK) + { + USBH_Delay(2); + phost->device.address = USBH_DEVICE_ADDRESS; + + /* user callback for device address assigned */ + USBH_UsrLog("Address (#%d) assigned.", phost->device.address); + phost->EnumState = ENUM_GET_CFG_DESC; + + /* modify control channels to update device address */ + USBH_OpenPipe (phost, + phost->Control.pipe_in, + 0x80, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + + /* Open Control pipes */ + USBH_OpenPipe (phost, + phost->Control.pipe_out, + 0x00, + phost->device.address, + phost->device.speed, + USBH_EP_CONTROL, + phost->Control.pipe_size); + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if ( USBH_Get_CfgDesc(phost, + USB_CONFIGURATION_DESC_SIZE) == USBH_OK) + { + phost->EnumState = ENUM_GET_FULL_CFG_DESC; + } + break; + + case ENUM_GET_FULL_CFG_DESC: + /* get FULL config descriptor (config, interface, endpoints) */ + if (USBH_Get_CfgDesc(phost, + phost->device.CfgDesc.wTotalLength) == USBH_OK) + { + phost->EnumState = ENUM_GET_MFC_STRING_DESC; + } + break; + + case ENUM_GET_MFC_STRING_DESC: + if (phost->device.DevDesc.iManufacturer != 0) + { /* Check that Manufacturer String is available */ + + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iManufacturer, + phost->device.Data , + 0xff) == USBH_OK) + { + /* User callback for Manufacturing string */ + USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + } + else + { + USBH_UsrLog("Manufacturer : N/A"); + phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_PRODUCT_STRING_DESC: + if (phost->device.DevDesc.iProduct != 0) + { /* Check that Product string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iProduct, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Product string */ + USBH_UsrLog("Product : %s", (char *)phost->device.Data); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; + } + } + else + { + USBH_UsrLog("Product : N/A"); + phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + case ENUM_GET_SERIALNUM_STRING_DESC: + if (phost->device.DevDesc.iSerialNumber != 0) + { /* Check that Serial number string is available */ + if ( USBH_Get_StringDesc(phost, + phost->device.DevDesc.iSerialNumber, + phost->device.Data, + 0xff) == USBH_OK) + { + /* User callback for Serial number string */ + USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data); + Status = USBH_OK; + } + } + else + { + USBH_UsrLog("Serial Number : N/A"); + Status = USBH_OK; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); +#endif + } + break; + + default: + break; + } + return Status; +} + +/** + * @brief USBH_LL_SetTimer + * Set the initial Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t time) +{ + phost->Timer = time; +} +/** + * @brief USBH_LL_IncTimer + * Increment Host Timer tick + * @param phost: Host Handle + * @retval None + */ +void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) +{ + phost->Timer ++; + USBH_HandleSof(phost); +} + +/** + * @brief USBH_HandleSof + * Call SOF process + * @param phost: Host Handle + * @retval None + */ +void USBH_HandleSof (USBH_HandleTypeDef *phost) +{ + if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL)) + { + phost->pActiveClass->SOFProcess(phost); + } +} +/** + * @brief USBH_LL_Connect + * Handle USB Host connexion event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) +{ + if(phost->gState == HOST_IDLE ) + { + phost->device.is_connected = 1; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_CONNECTION); + } + } + else if (phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT) + { + //On a cold boot with a low-speed device pre-attached, + //we get a second port-connected interrupt!??? + //So go back and do the port reset again... + phost->gState = HOST_IDLE; + } + return USBH_OK; +} + + + +USBH_StatusTypeDef USBH_LL_PortEnabled (USBH_HandleTypeDef *phost) +{ + if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT ) + { + phost->gState = HOST_DEV_ATTACHED ; + } + return USBH_OK; +} + + +/** + * @brief USBH_LL_Disconnect + * Handle USB Host disconnection event + * @param phost: Host Handle + * @retval USBH_Status + */ +USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost) +{ + //Ignore false disconnect interrupt that sometimes intrudes + //while we are waiting for the port to enable :( + if (phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT) + { + return USBH_FAIL; + } + + /*Stop Host */ + USBH_LL_Stop(phost); + + /* FRee Control Pipes */ + USBH_FreePipe (phost, phost->Control.pipe_in); + USBH_FreePipe (phost, phost->Control.pipe_out); + + phost->device.is_connected = 0; + + if(phost->pUser != NULL) + { + phost->pUser(phost, HOST_USER_DISCONNECTION); + } + USBH_UsrLog("USB Device disconnected"); + + /* Start the low level driver */ + USBH_LL_Start(phost); + + phost->gState = HOST_DEV_DISCONNECTED; + +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); +#endif + + return USBH_OK; +} + + +#if (USBH_USE_OS == 1) +/** + * @brief USB Host Thread task + * @param pvParameters not used + * @retval None + */ +static void USBH_Process_OS(void const * argument) +{ + osEvent event; + + for(;;) + { + event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever ); + + if( event.status == osEventMessage ) + { + USBH_Process((USBH_HandleTypeDef *)argument); + } + } +} + +/** +* @brief USBH_LL_NotifyURBChange +* Notify URB state Change +* @param phost: Host handle +* @retval USBH Status +*/ +USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost) +{ + osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); + return USBH_OK; +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.c new file mode 100644 index 0000000..f9b8f6d --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.c @@ -0,0 +1,870 @@ +/** + ****************************************************************************** + * @file usbh_ctlreq.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements the control requests for device enumeration + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbh_ctlreq.h" + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_CTLREQ +* @brief This file implements the standard requests for device enumeration +* @{ +*/ + + +/** @defgroup USBH_CTLREQ_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USBH_CTLREQ_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Variables +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_CTLREQ_Private_FunctionPrototypes +* @{ +*/ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost); + +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length); + +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length); + + +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); +static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); + + +/** +* @} +*/ + + +/** @defgroup USBH_CTLREQ_Private_Functions +* @{ +*/ + + +/** + * @brief USBH_Get_DevDesc + * Issue Get Device Descriptor command to the device. Once the response + * received, it parses the device descriptor and updates the status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint16_t length) +{ + USBH_StatusTypeDef status; + + if (length > USBH_MAX_DATA_BUFFER) + { + length = USBH_MAX_DATA_BUFFER; + } + + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_DEVICE, + 0, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length); + } + return status; +} + +/** + * @brief USBH_Get_CfgDesc + * Issues Configuration Descriptor to the device. Once the response + * received, it parses the configuration descriptor and updates the + * status. + * @param phost: Host Handle + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, + uint16_t length) + +{ + USBH_StatusTypeDef status; + uint8_t *pData; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1) + pData = phost->device.CfgDesc_Raw; + + if (length > USBH_MAX_SIZE_CONFIGURATION) + { + length = USBH_MAX_SIZE_CONFIGURATION; + } +#else + pData = phost->device.Data; + + if (length > USBH_MAX_DATA_BUFFER) + { + length = USBH_MAX_DATA_BUFFER; + } +#endif + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_CONFIGURATION, + 0, + pData, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseCfgDesc (&phost->device.CfgDesc, + pData, + length); + + } + return status; +} + + +/** + * @brief USBH_Get_StringDesc + * Issues string Descriptor command to the device. Once the response + * received, it parses the string descriptor and updates the status. + * @param phost: Host Handle + * @param string_index: String index for the descriptor + * @param buff: Buffer address for the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, + uint8_t string_index, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + + if (length > USBH_MAX_DATA_BUFFER) + { + length = USBH_MAX_DATA_BUFFER; + } + + if((status = USBH_GetDescriptor(phost, + USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, + USB_DESC_STRING | string_index, + 0x0409, + phost->device.Data, + length)) == USBH_OK) + { + /* Commands successfully sent and Response Received */ + USBH_ParseStringDesc(phost->device.Data,buff, length); + } + return status; +} + +/** + * @brief USBH_GetDescriptor + * Issues Descriptor command to the device. Once the response received, + * it parses the descriptor and updates the status. + * @param phost: Host Handle + * @param req_type: Descriptor type + * @param value_idx: Value for the GetDescriptr request + * @param buff: Buffer to store the descriptor + * @param length: Length of the descriptor + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, + uint8_t req_type, + uint16_t type_idx, + uint16_t value, + uint8_t* buff, + uint16_t length ) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_D2H | req_type; + phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; + phost->Control.setup.b.wValue.w = type_idx; + phost->Control.setup.b.wIndex.w = value; + phost->Control.setup.b.wLength.w = length; + } + return USBH_CtlReq(phost, buff , length ); +} + +/** + * @brief USBH_SetAddress + * This command sets the address to the connected device + * @param phost: Host Handle + * @param DeviceAddress: Device address to assign + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, + uint8_t DeviceAddress) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS; + + phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetCfg + * The command sets the configuration value to the connected device + * @param phost: Host Handle + * @param cfg_idx: Configuration value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, + uint16_t cfg_idx) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\ + USB_REQ_TYPE_STANDARD; + phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION; + phost->Control.setup.b.wValue.w = cfg_idx; + phost->Control.setup.b.wIndex.w = 0; + phost->Control.setup.b.wLength.w = 0; + } + + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_SetInterface + * The command sets the Interface value to the connected device + * @param phost: Host Handle + * @param altSetting: Interface value + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, + uint8_t ep_num, uint8_t altSetting) +{ + + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \ + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE; + phost->Control.setup.b.wValue.w = altSetting; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ClrFeature + * This request is used to clear or disable a specific feature. + * @param phost: Host Handle + * @param ep_num: endpoint number + * @param hc_num: Host channel number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, + uint8_t ep_num) +{ + if(phost->RequestState == CMD_SEND) + { + phost->Control.setup.b.bmRequestType = USB_H2D | + USB_REQ_RECIPIENT_ENDPOINT | + USB_REQ_TYPE_STANDARD; + + phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE; + phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT; + phost->Control.setup.b.wIndex.w = ep_num; + phost->Control.setup.b.wLength.w = 0; + } + return USBH_CtlReq(phost, 0 , 0 ); +} + +/** + * @brief USBH_ParseDevDesc + * This function Parses the device descriptor + * @param dev_desc: device_descriptor destination address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc, + uint8_t *buf, + uint16_t length) +{ + dev_desc->bLength = *(uint8_t *) (buf + 0); + dev_desc->bDescriptorType = *(uint8_t *) (buf + 1); + dev_desc->bcdUSB = LE16 (buf + 2); + dev_desc->bDeviceClass = *(uint8_t *) (buf + 4); + dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5); + dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6); + dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7); + + if (length > 8) + { /* For 1st time after device connection, Host may issue only 8 bytes for + Device Descriptor Length */ + dev_desc->idVendor = LE16 (buf + 8); + dev_desc->idProduct = LE16 (buf + 10); + dev_desc->bcdDevice = LE16 (buf + 12); + dev_desc->iManufacturer = *(uint8_t *) (buf + 14); + dev_desc->iProduct = *(uint8_t *) (buf + 15); + dev_desc->iSerialNumber = *(uint8_t *) (buf + 16); + dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17); + } +} + +/** + * @brief USBH_ParseCfgDesc + * This function Parses the configuration descriptor + * @param cfg_desc: Configuration Descriptor address + * @param buf: Buffer where the source descriptor is available + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, + uint8_t *buf, + uint16_t length) +{ + USBH_InterfaceDescTypeDef *pif ; + USBH_EpDescTypeDef *pep; + USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; + uint16_t ptr; + int8_t if_ix = 0; + int8_t ep_ix = 0; + + pdesc = (USBH_DescHeader_t *)buf; + + /* Parse configuration descriptor */ + cfg_desc->bLength = *(uint8_t *) (buf + 0); + cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1); + cfg_desc->wTotalLength = LE16 (buf + 2); + cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4); + cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5); + cfg_desc->iConfiguration = *(uint8_t *) (buf + 6); + cfg_desc->bmAttributes = *(uint8_t *) (buf + 7); + cfg_desc->bMaxPower = *(uint8_t *) (buf + 8); + + + if (length > USB_CONFIGURATION_DESC_SIZE) + { + ptr = USB_LEN_CFG_DESC; + pif = (USBH_InterfaceDescTypeDef *)0; + + //*************** + //Todo: This does not check for malformed descriptors. Needs hardening! + //*************** + while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) + { + pif = &cfg_desc->Itf_Desc[if_ix]; + USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); + + ep_ix = 0; + pep = (USBH_EpDescTypeDef *)0; + while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) + { + pdesc = USBH_GetNextDesc((uint8_t*) pdesc, &ptr); + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix]; + USBH_ParseEPDesc (pep, (uint8_t *)pdesc); + ep_ix++; + } + } + if_ix++; + } + } + } +} + + + +/** + * @brief USBH_ParseInterfaceDesc + * This function Parses the interface descriptor + * @param if_descriptor : Interface descriptor destination + * @param buf: Buffer where the descriptor data is available + * @retval None + */ +static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, + uint8_t *buf) +{ + if_descriptor->bLength = *(uint8_t *) (buf + 0); + if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2); + if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3); + if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4); + if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5); + if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6); + if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); + if_descriptor->iInterface = *(uint8_t *) (buf + 8); +} + +/** + * @brief USBH_ParseEPDesc + * This function Parses the endpoint descriptor + * @param ep_descriptor: Endpoint descriptor destination address + * @param buf: Buffer where the parsed descriptor stored + * @retval None + */ +static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, + uint8_t *buf) +{ + + ep_descriptor->bLength = *(uint8_t *) (buf + 0); + ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); + ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2); + ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3); + ep_descriptor->wMaxPacketSize = LE16 (buf + 4); + ep_descriptor->bInterval = *(uint8_t *) (buf + 6); +} + +/** + * @brief USBH_ParseStringDesc + * This function Parses the string descriptor + * @param psrc: Source pointer containing the descriptor data + * @param pdest: Destination address pointer + * @param length: Length of the descriptor + * @retval None + */ +static void USBH_ParseStringDesc (uint8_t* psrc, + uint8_t* pdest, + uint16_t length) +{ + uint16_t strlength; + uint16_t idx; + + /* The UNICODE string descriptor is not NULL-terminated. The string length is + computed by substracting two from the value of the first byte of the descriptor. + */ + + /* Check which is lower size, the Size of string or the length of bytes read + from the device */ + + if ( psrc[1] == USB_DESC_TYPE_STRING) + { /* Make sure the Descriptor is String Type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); + psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */ + + for (idx = 0; idx < strlength; idx+=2 ) + {/* Copy Only the string and ignore the UNICODE ID, hence add the src */ + *pdest = psrc[idx]; + pdest++; + } + *pdest = 0; /* mark end of string */ + } +} + +/** + * @brief USBH_GetNextDesc + * This function return the next descriptor header + * @param buf: Buffer where the cfg descriptor is available + * @param ptr: data pointer inside the cfg descriptor + * @retval next header + */ +USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr) +{ + USBH_DescHeader_t *pnext; + + *ptr += ((USBH_DescHeader_t *)pbuf)->bLength; + pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \ + ((USBH_DescHeader_t *)pbuf)->bLength); + + return(pnext); +} + + +/** + * @brief USBH_CtlReq + * USBH_CtlReq sends a control request and provide the status after + * completion of the request + * @param phost: Host Handle + * @param req: Setup Request Structure + * @param buff: data buffer address to store the response + * @param length: length of the response + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length) +{ + USBH_StatusTypeDef status; + status = USBH_BUSY; + + switch (phost->RequestState) + { + case CMD_SEND: + /* Start a SETUP transfer */ + phost->Control.buff = buff; + phost->Control.length = length; + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_WAIT; + status = USBH_BUSY; +#if (USBH_USE_OS == 1) + osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); +#endif + break; + + case CMD_WAIT: + status = USBH_HandleControl(phost); + if (status != USBH_BUSY) + { + phost->RequestState = CMD_SEND; + phost->Control.state = CTRL_IDLE; + } + break; + + default: + break; + } + return status; +} + +/** + * @brief USBH_HandleControl + * Handles the USB control transfer state machine + * @param phost: Host Handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost) +{ + uint8_t direction; + USBH_StatusTypeDef status = USBH_BUSY; + USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; + + switch (phost->Control.state) + { + case CTRL_SETUP: + /* send a SETUP packet */ + phost->Control.timer = phost->Timer; + USBH_CtlSendSetup(phost, + (uint8_t *)phost->Control.setup.d8 , + phost->Control.pipe_out); + phost->Control.state = CTRL_SETUP_WAIT; + break; + + case CTRL_SETUP_WAIT: + URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); + /* case SETUP packet sent successfully */ + if(URB_Status == USBH_URB_DONE) + { + direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); + + /* check if there is a data stage */ + if (phost->Control.setup.b.wLength.w != 0 ) + { + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_DATA_IN; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_DATA_OUT; + } + } + /* No DATA stage */ + else + { + /* If there is No Data Transfer Stage */ + if (direction == USB_D2H) + { + /* Data Direction is IN */ + phost->Control.state = CTRL_STATUS_OUT; + } + else + { + /* Data Direction is OUT */ + phost->Control.state = CTRL_STATUS_IN; + } + } + } + else if(URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + } + else if (URB_Status == USBH_URB_NOTREADY) + { + //Some mice cause a transaction error interrupt (HCINT_TXERR) at this point. + //Other mice just NAK our transaction. + //Either way we need to retry, but keep our original timeout so we don't wait forever. + USBH_CtlSendSetup(phost, + (uint8_t *)phost->Control.setup.d8 , + phost->Control.pipe_out); + } + + if ((int32_t)(phost->Timer - phost->Control.timer) >= USBH_CTRL_TRANSACTION_TIMEOUT_MS) + { + phost->Control.state = CTRL_ERROR; + } + break; + + case CTRL_DATA_IN: + /* Issue an IN token */ + phost->Control.timer = phost->Timer; + USBH_CtlReceiveData(phost, + phost->Control.buff, + phost->Control.length, + phost->Control.pipe_in); + + phost->Control.state = CTRL_DATA_IN_WAIT; + break; + + case CTRL_DATA_IN_WAIT: + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + /* check is DATA packet transferred successfully */ + if (URB_Status == USBH_URB_DONE) + { + phost->Control.state = CTRL_STATUS_OUT; + } + + /* manage error cases*/ + if (URB_Status == USBH_URB_STALL) + { + //Command not supported, report to callee + status = USBH_NOT_SUPPORTED; + } + else if (URB_Status == USBH_URB_ERROR) + { + /* Device error */ + phost->Control.state = CTRL_ERROR; + } + + if ((int32_t)(phost->Timer - phost->Control.timer) >= USBH_CTRL_TRANSACTION_TIMEOUT_MS) + { + phost->Control.state = CTRL_ERROR; + } + break; + + case CTRL_DATA_OUT: + phost->Control.timer = phost->Timer; + USBH_CtlSendData (phost, + phost->Control.buff, + phost->Control.length , + phost->Control.pipe_out, + 1); + phost->Control.state = CTRL_DATA_OUT_WAIT; + break; + + case CTRL_DATA_OUT_WAIT: + URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); + + if (URB_Status == USBH_URB_DONE) + { /* If the Setup Pkt is sent successful, then change the state */ + phost->Control.state = CTRL_STATUS_IN; + } + + /* handle error cases */ + else if (URB_Status == USBH_URB_STALL) + { + //Command not supported, report to callee + status = USBH_NOT_SUPPORTED; + } + else if (URB_Status == USBH_URB_NOTREADY) + { + /* Nack received from device */ + phost->Control.state = CTRL_DATA_OUT; + } + else if (URB_Status == USBH_URB_ERROR) + { + /* device error */ + phost->Control.state = CTRL_ERROR; + status = USBH_FAIL; + } + + if ((int32_t)(phost->Timer - phost->Control.timer) >= USBH_CTRL_TRANSACTION_TIMEOUT_MS) + { + phost->Control.state = CTRL_ERROR; + } + break; + + + case CTRL_STATUS_IN: + /* Send 0 bytes out packet */ + phost->Control.timer = phost->Timer; + USBH_CtlReceiveData (phost, + 0, + 0, + phost->Control.pipe_in); + phost->Control.state = CTRL_STATUS_IN_WAIT; + break; + + case CTRL_STATUS_IN_WAIT: + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); + + if ( URB_Status == USBH_URB_DONE) + { /* Control transfers completed, Exit the State Machine */ + phost->Control.state = CTRL_COMPLETE; + status = USBH_OK; + } + + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + } + else if(URB_Status == USBH_URB_STALL) + { + //Command not supported, report to callee + status = USBH_NOT_SUPPORTED; + } + + if ((int32_t)(phost->Timer - phost->Control.timer) >= USBH_CTRL_TRANSACTION_TIMEOUT_MS) + { + phost->Control.state = CTRL_ERROR; + } + break; + + case CTRL_STATUS_OUT: + phost->Control.timer = phost->Timer; + USBH_CtlSendData (phost, + 0, + 0, + phost->Control.pipe_out, + 1); + phost->Control.state = CTRL_STATUS_OUT_WAIT; + break; + + case CTRL_STATUS_OUT_WAIT: + URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); + if (URB_Status == USBH_URB_DONE) + { + status = USBH_OK; + phost->Control.state = CTRL_COMPLETE; + } + else if (URB_Status == USBH_URB_NOTREADY) + { + phost->Control.state = CTRL_STATUS_OUT; + } + else if (URB_Status == USBH_URB_ERROR) + { + phost->Control.state = CTRL_ERROR; + } + + if ((int32_t)(phost->Timer - phost->Control.timer) >= USBH_CTRL_TRANSACTION_TIMEOUT_MS) + { + phost->Control.state = CTRL_ERROR; + } + break; + + case CTRL_ERROR: + /* + After a halt condition is encountered or an error is detected by the + host, a control endpoint is allowed to recover by accepting the next Setup + PID; i.e., recovery actions via some other pipe are not required for control + endpoints. For the Default Control Pipe, a device reset will ultimately be + required to clear the halt or error condition if the next Setup PID is not + accepted. + */ + if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT) + { + /* try to recover control */ +// USBH_LL_Stop(phost); + + /* Do the transmission again, starting from SETUP Packet */ + phost->Control.state = CTRL_SETUP; + phost->RequestState = CMD_SEND; + } + else + { + phost->pUser(phost, HOST_USER_UNRECOVERED_ERROR); + phost->Control.errorcount = 0; + USBH_ErrLog("Control error"); + status = USBH_FAIL; + } + break; + + default: + break; + } + return status; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ioreq.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ioreq.c new file mode 100644 index 0000000..e67787c --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_ioreq.c @@ -0,0 +1,358 @@ +/** + ****************************************************************************** + * @file usbh_ioreq.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file handles the issuing of the USB transactions + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_ioreq.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_IOREQ + * @brief This file handles the standard protocol processing (USB v2.0) + * @{ + */ + + +/** @defgroup USBH_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBH_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Variables + * @{ + */ +/** + * @} + */ +/** @defgroup USBH_IOREQ_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_IOREQ_Private_Functions + * @{ + */ + + + +/** + * @brief USBH_CtlSendSetup + * Sends the Setup Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be send to Device + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t pipe_num) +{ + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_SETUP, /* Type setup */ + buff, /* data buffer */ + USBH_SETUP_PKT_SIZE, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_CtlSendData + * Sends a data Packet to the Device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + + return USBH_OK; +} + + +/** + * @brief USBH_CtlReceiveData + * Receives the Device Response to the Setup Packet + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, + uint8_t* buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_CONTROL, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; + +} + + +/** + * @brief USBH_BulkSendData + * Sends the Bulk Packet to the device + * @param phost: Host Handle + * @param buff: Buffer pointer from which the Data will be sent to Device + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num, + uint8_t do_ping ) +{ + if(phost->device.speed != USBH_SPEED_HIGH) + { + do_ping = 0; + } + + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + do_ping); /* do ping (HS Only)*/ + return USBH_OK; +} + + +/** + * @brief USBH_BulkReceiveData + * Receives IN bulk packet from device + * @param phost: Host Handle + * @param buff: Buffer pointer in which the received data packet to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint16_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_BULK, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + return USBH_OK; +} + + +/** + * @brief USBH_InterruptReceiveData + * Receives the Device Response to the Interrupt IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_InterruptSendData + * Sends the data on Interrupt OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint8_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_INTERRUPT, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} + +/** + * @brief USBH_IsocReceiveData + * Receives the Device Response to the Isochronous IN token + * @param phost: Host Handle + * @param buff: Buffer pointer in which the response needs to be copied + * @param length: Length of the data to be received + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 1, /* Direction : IN */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + + return USBH_OK; +} + +/** + * @brief USBH_IsocSendData + * Sends the data on Isochronous OUT Endpoint + * @param phost: Host Handle + * @param buff: Buffer pointer from where the data needs to be copied + * @param length: Length of the data to be sent + * @param pipe_num: Pipe Number + * @retval USBH Status. + */ +USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, + uint8_t *buff, + uint32_t length, + uint8_t pipe_num) +{ + USBH_LL_SubmitURB (phost, /* Driver handle */ + pipe_num, /* Pipe index */ + 0, /* Direction : OUT */ + USBH_EP_ISO, /* EP type */ + USBH_PID_DATA, /* Type Data */ + buff, /* data buffer */ + length, /* data length */ + 0); + + return USBH_OK; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_pipes.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_pipes.c new file mode 100644 index 0000000..97048de --- /dev/null +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_pipes.c @@ -0,0 +1,205 @@ +/** + ****************************************************************************** + * @file usbh_pipes.c + * @author MCD Application Team + * @version V3.2.1 + * @date 26-June-2015 + * @brief This file implements functions for opening and closing Pipes + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 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_pipes.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_LIB_CORE +* @{ +*/ + +/** @defgroup USBH_PIPES + * @brief This file includes opening and closing Pipes + * @{ + */ + +/** @defgroup USBH_PIPES_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_PIPES_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBH_PIPES_Private_Functions + * @{ + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost); + + +/** + * @brief USBH_Open_Pipe + * Open a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @param dev_address: USB Device address allocated to attached device + * @param speed : USB device speed (Full/Low) + * @param ep_type: end point type (Bulk/int/ctl) + * @param mps: max pkt size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + USBH_LL_OpenPipe(phost, + pipe_num, + epnum, + dev_address, + speed, + ep_type, + mps); + + return USBH_OK; + +} + +/** + * @brief USBH_ClosePipe + * Close a pipe + * @param phost: Host Handle + * @param pipe_num: Pipe Number + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num) +{ + + USBH_LL_ClosePipe(phost, pipe_num); + + return USBH_OK; + +} + +/** + * @brief USBH_Alloc_Pipe + * Allocate a new Pipe + * @param phost: Host Handle + * @param ep_addr: End point for which the Pipe to be allocated + * @retval Pipe number + */ +uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr) +{ + uint16_t pipe; + + pipe = USBH_GetFreePipe(phost); + + if (pipe != 0xFFFF) + { + phost->Pipes[pipe] = 0x8000 | ep_addr; + } + return pipe; +} + +/** + * @brief USBH_Free_Pipe + * Free the USB Pipe + * @param phost: Host Handle + * @param idx: Pipe number to be freed + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx) +{ + if (idx < HOST_PIPE_COUNT) + { + phost->Pipes[idx] &= 0x7FFF; + } + return USBH_OK; +} + +/** + * @brief USBH_GetFreePipe + * @param phost: Host Handle + * Get a free Pipe number for allocation to a device endpoint + * @retval idx: Free Pipe number + */ +static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost) +{ + uint8_t idx = 0; + + //We need to limit allocated pipes to the number actually provided by hardware! + for (idx = 0 ; idx < ((HCD_HandleTypeDef*)phost->pData)->Init.Host_channels; idx++) + { + if ((phost->Pipes[idx] & 0x8000) == 0) + { + return idx; + } + } + return 0xFFFF; +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/Downstream/Src/downstream_hid.c b/Downstream/Src/downstream_hid.c new file mode 100644 index 0000000..a366f6f --- /dev/null +++ b/Downstream/Src/downstream_hid.c @@ -0,0 +1,451 @@ +/* + * downstream_hid.c + * + * Created on: Apr 10, 2016 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + + +#include "downstream_hid.h" +#include "downstream_statemachine.h" +#include "usbh_hid.h" +#include "stm32f4xx_hal.h" +#include "build_config.h" + + +#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + +extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c +extern InterfaceCommandClassTypeDef ConfiguredDeviceClass; //Do a cheap hard-link to downstream_statemachine.c, rather than keep a duplicate here + + +//Information required to extract the data we need from incoming device reports. +uint8_t ReportButtonBitOffset; +uint8_t ReportButtonBitLength; +uint8_t ReportXBitOffset; +uint8_t ReportXBitLength; +uint8_t ReportYBitOffset; +uint8_t ReportYBitLength; +uint8_t ReportWheelBitOffset; +uint8_t ReportWheelBitLength; + +//Stuff used while parsing HID report +uint8_t* ReportDataPointer; +uint8_t ItemHeader; +uint8_t ItemData; + + + +static HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void); +static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void); +static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend); +static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend); +static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, + uint8_t valueBitOffset, + uint8_t valueBitLength); + + +InterfaceCommandClassTypeDef Downstream_HID_ApproveConnectedDevice(void) +{ + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + +#ifdef CONFIG_MOUSE_ENABLED + if (HID_Handle->Protocol == HID_MOUSE_PROTOCOL) + { + if (Downstream_HID_Mouse_ParseReportDescriptor() == HAL_OK) + { + return COMMAND_CLASS_HID_MOUSE; //success! + } + } +#endif +#ifdef CONFIG_KEYBOARD_ENABLED + if (HID_Handle->Protocol == HID_KEYBRD_PROTOCOL) + { + return COMMAND_CLASS_HID_KEYBOARD; //success! + } +#endif + + //else: + return COMMAND_CLASS_INTERFACE; //fail +} + + +#ifdef CONFIG_MOUSE_ENABLED +static HAL_StatusTypeDef Downstream_HID_Mouse_ParseReportDescriptor(void) +{ + uint32_t currentReportBitIndex = 0; + uint8_t currentUsagePage = 0; + uint8_t currentUsageIndex = 0; + uint8_t xUsageIndex = 0xFF; + uint8_t yUsageIndex = 0xFF; + uint8_t wheelUsageIndex = 0xFF; + uint8_t currentReportSize = 0; + uint8_t currentReportCount = 0; + + ReportDataPointer = hUsbHostFS.device.Data; + + ReportButtonBitLength = 0; + ReportXBitLength = 0; + ReportYBitLength = 0; + ReportWheelBitLength = 0; + + while ((Downstream_HID_GetNextReportItem() == HAL_OK) && ((ReportButtonBitLength == 0) || + (ReportXBitLength == 0) || + (ReportYBitLength == 0) || + (ReportWheelBitLength == 0))) + { + switch (ItemHeader) + { + case HID_ITEM_USAGE_PAGE: + currentUsagePage = ItemData; + currentUsageIndex = 0; + xUsageIndex = 0xFF; + yUsageIndex = 0xFF; + wheelUsageIndex = 0xFF; + break; + + case HID_ITEM_COLLECTION: //Physical collections also clear the usage index... + if (ItemData == HID_ITEM_COLLECTION_PHYS) + { + currentUsageIndex = 0; + xUsageIndex = 0xFF; + yUsageIndex = 0xFF; + wheelUsageIndex = 0xFF; + } + break; + + case HID_ITEM_END_COLLECTION: //...and so do collection ends + currentUsageIndex = 0; + xUsageIndex = 0xFF; + yUsageIndex = 0xFF; + wheelUsageIndex = 0xFF; + break; + + case HID_ITEM_USAGE: + switch (ItemData) + { + case HID_ITEM_USAGE_X: + xUsageIndex = currentUsageIndex; + break; + + case HID_ITEM_USAGE_Y: + yUsageIndex = currentUsageIndex; + break; + + case HID_ITEM_USAGE_WHEEL: + wheelUsageIndex = currentUsageIndex; + break; + } + currentUsageIndex++; + break; + + case HID_ITEM_REPORT_SIZE: + currentReportSize = ItemData; + break; + + case HID_ITEM_REPORT_COUNT: + currentReportCount = ItemData; + break; + + case HID_ITEM_REPORT_ID: + currentReportBitIndex += 8; //Rudimentary support for a single report ID + break; + + case HID_ITEM_INPUT: + switch (currentUsagePage) + { + case HID_ITEM_USAGE_PAGE_BUTTON: + if (ItemData == HID_ITEM_INPUT_ABS) + { + //Buttons found! + if (currentReportSize != 1) + { + return HAL_ERROR; + } + ReportButtonBitOffset = currentReportBitIndex; + ReportButtonBitLength = currentReportCount; + if (ReportButtonBitLength > HID_MOUSE_MAX_BUTTONS) + { + ReportButtonBitLength = HID_MOUSE_MAX_BUTTONS; + } + } + break; + + case HID_ITEM_USAGE_PAGE_DESKTOP: + if (ItemData == HID_ITEM_INPUT_REL) + { + //Movement data found! + if ((currentReportSize < 8) || (currentReportSize > 16)) + { + return HAL_ERROR; + } + if (xUsageIndex != 0xFF) + { + ReportXBitOffset = currentReportBitIndex + (currentReportSize * xUsageIndex); + ReportXBitLength = currentReportSize; + if ((ReportXBitOffset + ReportXBitLength) > (HID_MAX_REPORT_LEN * 8)) + { + return HAL_ERROR; + } + } + if (yUsageIndex != 0xFF) + { + ReportYBitOffset = currentReportBitIndex + (currentReportSize * yUsageIndex); + ReportYBitLength = currentReportSize; + if ((ReportYBitOffset + ReportYBitLength) > (HID_MAX_REPORT_LEN * 8)) + { + return HAL_ERROR; + } + } + if (wheelUsageIndex != 0xFF) + { + ReportWheelBitOffset = currentReportBitIndex + (currentReportSize * wheelUsageIndex); + ReportWheelBitLength = currentReportSize; + if ((ReportWheelBitOffset + ReportWheelBitLength) > (HID_MAX_REPORT_LEN * 8)) + { + return HAL_ERROR; + } + } + } + break; + } + currentUsageIndex = 0; + xUsageIndex = 0xFF; + yUsageIndex = 0xFF; + wheelUsageIndex = 0xFF; + currentReportBitIndex += (currentReportSize * currentReportCount); + break; + } + } + + //We don't mind if we didn't find a scrollwheel item. + if ((ReportButtonBitLength == 0) || + (ReportXBitLength == 0) || + (ReportYBitLength == 0)) + { + return HAL_ERROR; + } + + return HAL_OK; +} + + +//Retrieves the next item in the HID report, and at most one of its associated data bytes. +//Then it updates ReportDataPointer based on the actual length of the retrieved item. +static HAL_StatusTypeDef Downstream_HID_GetNextReportItem(void) +{ + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + uint32_t itemLength; + + if ((ReportDataPointer >= &hUsbHostFS.device.Data[USBH_MAX_DATA_BUFFER]) || + ((ReportDataPointer - &hUsbHostFS.device.Data[0]) >= HID_Handle->HID_Desc.wItemLength)) + { + return HAL_ERROR; + } + + ItemHeader = *ReportDataPointer & HID_ITEM_MASK; + itemLength = *ReportDataPointer & HID_ITEM_LENGTH_MASK; + ReportDataPointer++; + + if (itemLength == 3) + { + itemLength = 4; //Length = 3 actually means 4 bytes + } + + if (ItemHeader == HID_ITEM_LONG) + { + itemLength += *ReportDataPointer; //Long items have another length byte + } + else + { + if (itemLength > 0) + { + ItemData = *ReportDataPointer; //If it is a short item, grab its first data byte + } + } + + ReportDataPointer += itemLength; + return HAL_OK; +} +#endif //#ifdef CONFIG_MOUSE_ENABLED + + + +void Downstream_HID_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) +{ + if (receivedPacket->Command == COMMAND_HID_GET_REPORT) + { + Downstream_ReleasePacket(receivedPacket); + if (USBH_HID_GetInterruptReport(&hUsbHostFS, + Downstream_HID_InterruptReportCallback) != HAL_OK) + { + Downstream_PacketProcessor_FreakOut(); + } + Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); + return; + } + +#ifdef CONFIG_KEYBOARD_ENABLED + if (receivedPacket->Command == COMMAND_HID_SET_REPORT) + { + if ((ConfiguredDeviceClass != COMMAND_CLASS_HID_KEYBOARD) || + (receivedPacket->Length16 != ((HID_KEYBOARD_OUTPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16) || + ((receivedPacket->Data[0] & ~((1 << HID_KEYBOARD_MAX_LED) - 1)) != 0)) + { + Downstream_PacketProcessor_FreakOut(); + } + USBH_HID_SetReport(&hUsbHostFS, + HID_REPORT_DIRECTION_OUT, + 0, + receivedPacket->Data, + HID_KEYBOARD_OUTPUT_DATA_LEN, + Downstream_HID_SendReportCallback); + Downstream_ReleasePacket(receivedPacket); + Downstream_PacketProcessor_NotifyDisconnectReplyRequired(); + return; + } +#endif //#ifdef CONFIG_KEYBOARD_ENABLED + + //else: + Downstream_PacketProcessor_FreakOut(); +} + + +void Downstream_HID_InterruptReportCallback(USBH_StatusTypeDef result) +{ + DownstreamPacketTypeDef* freePacket; + + freePacket = Downstream_GetFreePacketImmediately(); + + if (result == USBH_OK) + { + //Data received from device +#ifdef CONFIG_MOUSE_ENABLED + if (ConfiguredDeviceClass == COMMAND_CLASS_HID_MOUSE) + { + Downstream_HID_Mouse_ExtractDataFromReport(freePacket); + freePacket->Length16 = ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + } + else +#endif +#ifdef CONFIG_KEYBOARD_ENABLED + if (ConfiguredDeviceClass == COMMAND_CLASS_HID_KEYBOARD) + { + Downstream_HID_Keyboard_ExtractDataFromReport(freePacket); + freePacket->Length16 = ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + } + else +#endif + + //else if... + { + Downstream_PacketProcessor_FreakOut(); + return; + } + } + else + { + //NAK received from device, return zero-length packet + freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + } + + freePacket->CommandClass = ConfiguredDeviceClass; + freePacket->Command = COMMAND_HID_GET_REPORT; + Downstream_PacketProcessor_ClassReply(freePacket); +} + + +#ifdef CONFIG_MOUSE_ENABLED +static void Downstream_HID_Mouse_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) +{ + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + uint32_t readData; + + readData = *(uint32_t*)&(HID_Handle->Data[(ReportButtonBitOffset / 8)]); + readData >>= (ReportButtonBitOffset % 8); + readData &= ((1 << ReportButtonBitLength) - 1); //Truncate extra buttons + packetToSend->Data[0] = readData; + + packetToSend->Data[1] = Downstream_HID_Mouse_Extract8BitValue(HID_Handle, + ReportXBitOffset, + ReportXBitLength); + + packetToSend->Data[2] = Downstream_HID_Mouse_Extract8BitValue(HID_Handle, + ReportYBitOffset, + ReportYBitLength); + + packetToSend->Data[3] = Downstream_HID_Mouse_Extract8BitValue(HID_Handle, + ReportWheelBitOffset, + ReportWheelBitLength); +} + + + +static uint8_t Downstream_HID_Mouse_Extract8BitValue(HID_HandleTypeDef* hidHandle, + uint8_t valueBitOffset, + uint8_t valueBitLength) +{ + int32_t readData; + + readData = *(uint32_t*)&(hidHandle->Data[(valueBitOffset / 8)]); + readData >>= (valueBitOffset % 8); + if (readData & (1 << (valueBitLength - 1))) //If value is negative... + { + readData |= ~((1 << valueBitLength) - 1); //...sign-extend to full width... + } + else + { + readData &= (1 << valueBitLength) - 1; //...else zero out unwanted bits + } + if (readData < INT8_MIN) readData = INT8_MIN; //Limit to 8-bit values + if (readData > INT8_MAX) readData = INT8_MAX; + return (int8_t)readData; +} +#endif //#ifdef CONFIG_MOUSE_ENABLED + + +#ifdef CONFIG_KEYBOARD_ENABLED +static void Downstream_HID_Keyboard_ExtractDataFromReport(DownstreamPacketTypeDef* packetToSend) +{ + HID_HandleTypeDef* HID_Handle = (HID_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + uint32_t i; + uint8_t readData; + + packetToSend->Data[0] = HID_Handle->Data[0]; //Modifier keys - pass straight through + packetToSend->Data[1] = 0; //Constant byte + + for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++) //Key array + { + readData = HID_Handle->Data[i]; + if (readData > HID_KEYBOARD_MAX_KEY) + { + readData = HID_KEYBOARD_MAX_KEY; + } + packetToSend->Data[i] = readData; + } +} +#endif //#ifdef CONFIG_KEYBOARD_ENABLED + + + +void Downstream_HID_SendReportCallback(USBH_StatusTypeDef result) +{ + UNUSED(result); + + DownstreamPacketTypeDef* freePacket; + + freePacket = Downstream_GetFreePacketImmediately(); + freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + freePacket->CommandClass = ConfiguredDeviceClass; + freePacket->Command = COMMAND_HID_SET_REPORT; + Downstream_PacketProcessor_ClassReply(freePacket); +} + + +#endif //#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + diff --git a/Downstream/Src/downstream_msc.c b/Downstream/Src/downstream_msc.c new file mode 100644 index 0000000..7111ce9 --- /dev/null +++ b/Downstream/Src/downstream_msc.c @@ -0,0 +1,358 @@ +/* + * downstream_msc.c + * + * Created on: 8/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include "downstream_msc.h" +#include "downstream_interface_def.h" +#include "downstream_statemachine.h" +#include "downstream_spi.h" +#include "usbh_msc.h" +#include "build_config.h" +#include "led.h" + + +#ifdef CONFIG_MASS_STORAGE_ENABLED + +extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c + + +//Stuff we need to save for our callbacks to use: +DownstreamMSCCallbackPacketTypeDef GetStreamDataCallback; +uint32_t ByteCount; +DownstreamPacketTypeDef* ReadStreamPacket; +uint8_t ReadStreamBusy; + + +static void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_TestUnitReadyCallback(USBH_StatusTypeDef result); +static void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef result); +static void Downstream_MSC_GetStreamDataPacketCallback(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_Disconnect(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_MSC_PacketProcessor_DisconnectCallback(USBH_StatusTypeDef result); + + +//High-level checks on the connected device. We don't want some weirdly +//configured device to bomb our USB stack, accidentally or otherwise. +InterfaceCommandClassTypeDef Downstream_MSC_ApproveConnectedDevice(void) +{ + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if (MSC_Handle->unit[MSC_FIXED_LUN].error != MSC_OK) + { + return COMMAND_CLASS_INTERFACE; //fail + } + + if ((MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == 0) || + (MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == UINT32_MAX)) + { + return COMMAND_CLASS_INTERFACE; //fail + } + + if (MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size != MSC_SUPPORTED_BLOCK_SIZE) + { + return COMMAND_CLASS_INTERFACE; //fail + } + + return COMMAND_CLASS_MASS_STORAGE; //success! +} + + +void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) +{ + switch (receivedPacket->Command) + { + case COMMAND_MSC_TEST_UNIT_READY: + Downstream_MSC_PacketProcessor_TestUnitReady(receivedPacket); + break; + + case COMMAND_MSC_GET_CAPACITY: + Downstream_MSC_PacketProcessor_GetCapacity(receivedPacket); + break; + + case COMMAND_MSC_READ: + Downstream_MSC_PacketProcessor_BeginRead(receivedPacket); + break; + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + case COMMAND_MSC_WRITE: + Downstream_MSC_PacketProcessor_BeginWrite(receivedPacket); + break; +#endif + + case COMMAND_MSC_DISCONNECT: + Downstream_MSC_PacketProcessor_Disconnect(receivedPacket); + break; + + case COMMAND_MSC_POLL_DISCONNECT: + Downstream_PacketProcessor_ClassReply(receivedPacket); //Device is still connected, so send the packet straight back + break; + + default: + Downstream_PacketProcessor_FreakOut(); + } + +} + + +static void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket) +{ + Downstream_ReleasePacket(receivedPacket); + + if (USBH_MSC_UnitIsReady(&hUsbHostFS, + MSC_FIXED_LUN, + Downstream_MSC_PacketProcessor_TestUnitReadyCallback) != USBH_BUSY) + { + Downstream_MSC_PacketProcessor_TestUnitReadyCallback(USBH_FAIL); + } +} + + +static void Downstream_MSC_PacketProcessor_TestUnitReadyCallback(USBH_StatusTypeDef result) +{ + DownstreamPacketTypeDef* freePacket; + + freePacket = Downstream_GetFreePacketImmediately(); + freePacket->CommandClass = COMMAND_CLASS_MASS_STORAGE; + freePacket->Command = COMMAND_MSC_TEST_UNIT_READY; + freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16 + 1; + + if (result == USBH_OK) + { + freePacket->Data[0] = HAL_OK; + } + else + { + freePacket->Data[0] = HAL_ERROR; + } + Downstream_PacketProcessor_ClassReply(freePacket); +} + + + +static void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receivedPacket) +{ + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + receivedPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16 + (8 / 2); + *(uint32_t*)&(receivedPacket->Data[0]) = MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr; + *(uint32_t*)&(receivedPacket->Data[4]) = (uint32_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; + Downstream_PacketProcessor_ClassReply(receivedPacket); +} + + + +static void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket) +{ + uint64_t readBlockAddress; + uint32_t readBlockCount; + uint64_t readByteCount; + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if (receivedPacket->Length16 != (DOWNSTREAM_PACKET_HEADER_LEN_16 + ((4 * 3) / 2))) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + LED_SetState(LED_STATUS_FLASH_READWRITE); + readBlockAddress = *(uint64_t*)&(receivedPacket->Data[0]); + readBlockCount = *(uint32_t*)&(receivedPacket->Data[8]); + readByteCount = readBlockCount * MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; + if ((readBlockAddress >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + ((readBlockAddress + readBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + (readByteCount > UINT32_MAX)) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + receivedPacket->Data[0] = HAL_ERROR; + receivedPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16 + 1; + if (USBH_MSC_Read(&hUsbHostFS, + MSC_FIXED_LUN, + (uint32_t)readBlockAddress, + readBlockCount, + Downstream_MSC_PacketProcessor_RdWrCompleteCallback) == USBH_BUSY) + { + Downstream_ReleasePacket(receivedPacket); + return; + } + + //Fail: + Downstream_PacketProcessor_ClassReply(receivedPacket); +} + + +static void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef result) +{ + if (result != USBH_OK) + { + Downstream_GetFreePacket(Downstream_PacketProcessor_GenericErrorReply); + return; + } + Downstream_ReceivePacket(Downstream_PacketProcessor); +} + + + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED +static void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* receivedPacket) +{ + uint64_t writeBlockAddress; + uint32_t writeBlockCount; + uint64_t writeByteCount; + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if (receivedPacket->Length16 != (DOWNSTREAM_PACKET_HEADER_LEN_16 + ((4 * 3) / 2))) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + writeBlockAddress = *(uint64_t*)&(receivedPacket->Data[0]); + writeBlockCount = *(uint32_t*)&(receivedPacket->Data[8]); + writeByteCount = writeBlockCount * MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; + if ((writeBlockAddress >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + ((writeBlockAddress + writeBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + (writeByteCount > UINT32_MAX)) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + ReadStreamPacket = NULL; //Prepare for GetStreamDataPacket's use + ReadStreamBusy = 0; + ByteCount = (uint32_t)writeByteCount; + + receivedPacket->Data[0] = HAL_ERROR; + receivedPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16 + 1; + + //Our host stack has no way to detect if write-protection is enabled. + //So currently we can't return HAL_BUSY to Upstream in this situation. + if (USBH_MSC_Write(&hUsbHostFS, + MSC_FIXED_LUN, + (uint32_t)writeBlockAddress, + writeBlockCount, + Downstream_MSC_PacketProcessor_RdWrCompleteCallback) == USBH_BUSY) + { + Downstream_ReleasePacket(receivedPacket); + return; + } + + //Fail: + Downstream_PacketProcessor_ClassReply(receivedPacket); +} +#endif + + +//Used by USB MSC host driver +HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* packetToSend, + uint32_t dataLength8) +{ + if ((dataLength8 % 2) != 0) + { + return HAL_ERROR; + } + + packetToSend->Length16 = (dataLength8 / 2) + DOWNSTREAM_PACKET_HEADER_LEN_16; + packetToSend->CommandClass = COMMAND_CLASS_MASS_STORAGE | COMMAND_CLASS_DATA_FLAG; + packetToSend->Command = COMMAND_MSC_READ; + return Downstream_TransmitPacket(packetToSend); +} + + +#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED +//Used by USB MSC host driver +HAL_StatusTypeDef Downstream_MSC_GetStreamDataPacket(DownstreamMSCCallbackPacketTypeDef callback) +{ + GetStreamDataCallback = callback; + + if (ReadStreamBusy != 0) + { + return HAL_OK; + } + ReadStreamBusy = 1; + + if (ReadStreamPacket && GetStreamDataCallback) //Do we have a stored packet and an address to send it? + { + Downstream_MSC_GetStreamDataPacketCallback(ReadStreamPacket); //Send it now! + ReadStreamPacket = NULL; + return HAL_OK; //Our callback will call us again, so we don't need to get a packet in this case. + } + return Downstream_ReceivePacket(Downstream_MSC_GetStreamDataPacketCallback); +} + + +void Downstream_MSC_GetStreamDataPacketCallback(DownstreamPacketTypeDef* receivedPacket) +{ + uint16_t dataLength8; + + ReadStreamBusy = 0; + if (GetStreamDataCallback == NULL) + { + ReadStreamPacket = receivedPacket; //We used up our callback already, so save this one for later. + return; + } + + dataLength8 = (receivedPacket->Length16 - DOWNSTREAM_PACKET_HEADER_LEN_16) * 2; + + if ((receivedPacket->CommandClass != (COMMAND_CLASS_MASS_STORAGE | COMMAND_CLASS_DATA_FLAG)) || //Must be MSC command with data flag set + (receivedPacket->Command != COMMAND_MSC_WRITE) || //Must be write command + (receivedPacket->Length16 <= DOWNSTREAM_PACKET_HEADER_LEN_16) || //Should be at least one data byte in the packet. + (dataLength8 > ByteCount)) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + + ByteCount -= dataLength8; + GetStreamDataCallback(receivedPacket, dataLength8); //usb_msc_scsi will use this packet, so don't release now + if (ByteCount > 0) + { + Downstream_MSC_GetStreamDataPacket(NULL); //Try to get the next packet now, before USB asks for it + } + +} +#endif //#ifdef CONFIG_MASS_STORAGE_WRITES_PERMITTED + + + +static void Downstream_MSC_PacketProcessor_Disconnect(DownstreamPacketTypeDef* receivedPacket) +{ + Downstream_ReleasePacket(receivedPacket); + + USBH_MSC_StartStopUnit(&hUsbHostFS, + MSC_FIXED_LUN, + MSC_START_STOP_EJECT_FLAG, + Downstream_MSC_PacketProcessor_DisconnectCallback); +} + + + +static void Downstream_MSC_PacketProcessor_DisconnectCallback(USBH_StatusTypeDef result) +{ + DownstreamPacketTypeDef* freePacket; + + if (result == USBH_OK) + { + freePacket = Downstream_GetFreePacketImmediately(); + freePacket->CommandClass = COMMAND_CLASS_MASS_STORAGE; + freePacket->Command = COMMAND_MSC_DISCONNECT; + freePacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + Downstream_PacketProcessor_ClassReply(freePacket); + } +} + +#endif //#ifdef CONFIG_MASS_STORAGE_ENABLED + diff --git a/Downstream/Src/downstream_spi.c b/Downstream/Src/downstream_spi.c new file mode 100644 index 0000000..18f8b03 --- /dev/null +++ b/Downstream/Src/downstream_spi.c @@ -0,0 +1,419 @@ +/* + * upstream_spi.c + * + * Created on: 24/07/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include "downstream_interface_def.h" +#include "downstream_spi.h" +#include "downstream_statemachine.h" +#include "board_config.h" +#include "led.h" + + +SPI_HandleTypeDef Hspi1; +DownstreamPacketTypeDef DownstreamPacket0; +DownstreamPacketTypeDef DownstreamPacket1; +DownstreamPacketTypeDef* CurrentWorkingPacket; +DownstreamPacketTypeDef* NextTxPacket = NULL; + +InterfaceStateTypeDef DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; +FreePacketCallbackTypeDef PendingFreePacketCallback = NULL; //Indicates someone is waiting for a packet buffer to become available +SpiPacketReceivedCallbackTypeDef ReceivePacketCallback = NULL; //Indicates someone is waiting for a received packet + +uint32_t TemporaryIncomingPacketLength = 0; +uint8_t SpiInterruptCompleted = 0; + + +HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void); +void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket); + + + +void Downstream_InitSPI(void) +{ + DownstreamPacket0.Busy = NOT_BUSY; + DownstreamPacket1.Busy = NOT_BUSY; + + Hspi1.Instance = SPI1; + Hspi1.Init.Mode = SPI_MODE_SLAVE; + Hspi1.Init.Direction = SPI_DIRECTION_2LINES; + Hspi1.Init.DataSize = SPI_DATASIZE_16BIT; + Hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + Hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + Hspi1.Init.NSS = SPI_NSS_HARD_INPUT; + Hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + Hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + Hspi1.Init.TIMode = SPI_TIMODE_DISABLED; + Hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; + Hspi1.Init.CRCPolynomial = SPI_CRC_DEFAULTPOLYNOMIAL; + HAL_SPI_Init(&Hspi1); +} + + +//Used by downstream state machine and USB host classes. +HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return HAL_ERROR; + } + + //Do we already have a queued callback? + if (PendingFreePacketCallback != NULL) + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + + //Check if there is a free buffer now + if (DownstreamPacket0.Busy == NOT_BUSY) + { + DownstreamPacket0.Busy = BUSY; + callback(&DownstreamPacket0); + return HAL_OK; + } + if (DownstreamPacket1.Busy == NOT_BUSY) + { + DownstreamPacket1.Busy = BUSY; + callback(&DownstreamPacket1); + return HAL_OK; + } + + //Otherwise save requested address for when a buffer becomes free in the future + PendingFreePacketCallback = callback; + return HAL_OK; +} + + + +DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return NULL; + } + + //We are expecting a free buffer now + if (DownstreamPacket0.Busy == NOT_BUSY) + { + DownstreamPacket0.Busy = BUSY; + return &DownstreamPacket0; + } + if (DownstreamPacket1.Busy == NOT_BUSY) + { + DownstreamPacket1.Busy = BUSY; + return &DownstreamPacket1; + } + + //Should not happen: + DOWNSTREAM_SPI_FREAKOUT; + return NULL; +} + + + +//Used by Downstream state machine and USB host classes. +void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease) +{ + FreePacketCallbackTypeDef tempCallback; + + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return; + } + + if ((packetToRelease != &DownstreamPacket0) && + (packetToRelease != &DownstreamPacket1)) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + + if (PendingFreePacketCallback != NULL) + { + tempCallback = PendingFreePacketCallback; //In extreme situations, running this callback can trigger another request for a free packet, + PendingFreePacketCallback = NULL; //thereby causing GetFreePacket to freak out. So we need to clear the callback indicator first. + tempCallback(packetToRelease); + } + else + { + packetToRelease->Busy = NOT_BUSY; + } +} + + +//Used by Downstream state machine and USB classes. +//Ok to call when idle or transmitting. +//Not OK to call when receiving or awaiting reception. +HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return HAL_ERROR; + } + + if ((DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) || + (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_PACKET_WAIT) || + (ReceivePacketCallback != NULL)) + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + + ReceivePacketCallback = callback; + return Downstream_CheckPreparePacketReception(); +} + + +//Internal use only +HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return HAL_ERROR; + } + + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_IDLE) + { + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_SIZE_WAIT; + return Downstream_GetFreePacket(Downstream_PrepareReceivePacketSize); + } + return HAL_OK; +} + + +//Internal use only +void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return; + } + + if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + CurrentWorkingPacket = freePacket; + CurrentWorkingPacket->Length16 = 0; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length16, + (uint8_t*)&CurrentWorkingPacket->Length16, + 2) != HAL_OK) //We only need to read one word, but the peripheral library freaks out... + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + + UPSTREAM_TX_REQUEST_ASSERT; +} + + + +//Used by Downstream state machine and USB classes. +//Call when idle or transmitting. +//It doesn't make sense to call when receiving or awaiting reception. +HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite) +{ + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return HAL_ERROR; + } + + //Sanity checks + if ((packetToWrite != &DownstreamPacket0) && + (packetToWrite != &DownstreamPacket1)) + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + if ((packetToWrite->Busy != BUSY) || + (packetToWrite->Length16 < DOWNSTREAM_PACKET_LEN_MIN_16) || + (packetToWrite->Length16 > DOWNSTREAM_PACKET_LEN_16)) + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + if (NextTxPacket != NULL) + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + + switch (DownstreamInterfaceState) + { + case DOWNSTREAM_INTERFACE_TX_SIZE_WAIT: + case DOWNSTREAM_INTERFACE_TX_PACKET_WAIT: + NextTxPacket = packetToWrite; + break; + + case DOWNSTREAM_INTERFACE_IDLE: + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_SIZE_WAIT; + CurrentWorkingPacket = packetToWrite; + + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length16, + (uint8_t*)&TemporaryIncomingPacketLength, + 2) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... + { + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + UPSTREAM_TX_REQUEST_ASSERT; + break; + + default: + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; + } + + return HAL_OK; +} + + + +//Do stuff at main loop priority after SPI transaction is complete +void Downstream_SPIProcess(void) +{ + SpiPacketReceivedCallbackTypeDef tempPacketCallback; + + if (SpiInterruptCompleted == 0) + { + return; + } + SpiInterruptCompleted = 0; + + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return; + } + + //Finished transmitting packet size + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_TX_SIZE_WAIT) + { + if ((uint16_t)TemporaryIncomingPacketLength != 0) + { + //Currently we just freak out if Upstream sends us an unexpected command. + //Theoretically we could reset our downstream state machine and accept the new command... + DOWNSTREAM_SPI_FREAKOUT; + return; + } + + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_PACKET_WAIT; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + &CurrentWorkingPacket->CommandClass, + &CurrentWorkingPacket->CommandClass, + ((CurrentWorkingPacket->Length16 < 2) ? 2 : CurrentWorkingPacket->Length16)) != HAL_OK) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + UPSTREAM_TX_REQUEST_ASSERT; + return; + } + + //Finished transmitting packet body + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_TX_PACKET_WAIT) + { + Downstream_ReleasePacket(CurrentWorkingPacket); + if (NextTxPacket != NULL) + { + //NextTxPacket has already passed the checks in Downstream_TransmitPacket. + //So we just need to pass it to HAL_SPI_Transmit_DMA. + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_SIZE_WAIT; + CurrentWorkingPacket = NextTxPacket; + NextTxPacket = NULL; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length16, + (uint8_t*)&TemporaryIncomingPacketLength, + 2) != HAL_OK) //We only need to write one word, but the peripheral library freaks out... + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + UPSTREAM_TX_REQUEST_ASSERT; + return; + } + + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; + if (ReceivePacketCallback != NULL) + { + Downstream_CheckPreparePacketReception(); + } + return; + } + + + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) + { + if ((CurrentWorkingPacket->Length16 < DOWNSTREAM_PACKET_LEN_MIN_16) || + (CurrentWorkingPacket->Length16 > DOWNSTREAM_PACKET_LEN_16)) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_PACKET_WAIT; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + &CurrentWorkingPacket->CommandClass, + &CurrentWorkingPacket->CommandClass, + ((CurrentWorkingPacket->Length16 < 2) ? 2 : CurrentWorkingPacket->Length16)) != HAL_OK) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + UPSTREAM_TX_REQUEST_ASSERT; + return; + } + + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_PACKET_WAIT) + { + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; + if (ReceivePacketCallback == NULL) + { + DOWNSTREAM_SPI_FREAKOUT; + return; + } + //Packet processor may want to receive another packet immediately, + //so clear ReceivePacketCallback before the call. + //It is the callback's responsibility to release the packet buffer we are passing to it! + tempPacketCallback = ReceivePacketCallback; + ReceivePacketCallback = NULL; + tempPacketCallback(CurrentWorkingPacket); + return; + } + + + //case default: + DOWNSTREAM_SPI_FREAKOUT; +} + + + +//Called at the end of the SPI TxRx DMA transfer, +//at DMA2 interrupt priority. Assume *hspi points to our hspi1. +//We use TxRx to send our reply packet to check if Upstream was trying +//to send us a packet at the same time. +//We also TxRx our packet body because the SPI silicon is buggy at the end of +//a transmit-only DMA transfer with CRC! (it does not clear RXNE flag on request) +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) +{ + UPSTREAM_TX_REQUEST_DEASSERT; + SpiInterruptCompleted = 1; +} + + + +//Something bad happened! Possibly CRC error... +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) +{ + DOWNSTREAM_SPI_FREAKOUT; +} + diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c new file mode 100644 index 0000000..66c5490 --- /dev/null +++ b/Downstream/Src/downstream_statemachine.c @@ -0,0 +1,338 @@ +/* + * downstream_statemachine.c + * + * Created on: 2/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include "downstream_statemachine.h" +#include "downstream_interface_def.h" +#include "downstream_spi.h" +#include "downstream_msc.h" +#include "downstream_hid.h" +#include "usbh_core.h" +#include "usbh_msc.h" +#include "usbh_hid.h" +#include "led.h" +#include "build_config.h" + + +DownstreamStateTypeDef DownstreamState = STATE_DEVICE_NOT_READY; +InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE; +uint8_t NotifyDisconnectReply = 0; + + +static void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); +static void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); +static void Downstream_PacketProcessor_NotifyDisconnectReply(DownstreamPacketTypeDef* packetToSend); + + +#ifdef CONFIG_USB_ID_ENABLED + +//usb device id def +typedef struct usb_id{ + uint16_t vendor; + uint16_t product; +}usb_device_id; + +#define USB_ID_COUNT 2 + +usb_device_id list[USB_ID_COUNT]={ + {0x046d,0xc077},//usb vendor,usb product, add your device to array and edit USB_ID_COUNT + // {0x046d,0xc0ff} //bad device test + {0x12c9,0x1017} //new mouse Fury +}; +#endif + +void Downstream_InitStateMachine(void) +{ + if ((DownstreamState != STATE_DEVICE_NOT_READY) || + (ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE)) + { + DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + Downstream_InitSPI(); + + //Prepare to receive our first packet from Upstream! + Downstream_ReceivePacket(Downstream_PacketProcessor); +} + + + +void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) +{ + if (DownstreamState >= STATE_ERROR) + { + Downstream_ReleasePacket(receivedPacket); + return; + } + + //Device not connected yet + if (DownstreamState != STATE_ACTIVE) + { + if (receivedPacket->CommandClass == COMMAND_CLASS_INTERFACE) + { + Downstream_PacketProcessor_Interface(receivedPacket); + } + else + { + //If we get a class-specific message when our device is disconnected, + //we need to tell Upstream of the fact (and not freak out). + Downstream_PacketProcessor_NotifyDisconnectReply(receivedPacket); + } + return; + } + + //Device is connected: expect only class-specific messages, + //and only to our currently active device class. + if ((ConfiguredDeviceClass == COMMAND_CLASS_INTERFACE) || + (ConfiguredDeviceClass != receivedPacket->CommandClass)) + { + DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + switch (ConfiguredDeviceClass) + { + +#ifdef CONFIG_MASS_STORAGE_ENABLED + case COMMAND_CLASS_MASS_STORAGE: + Downstream_MSC_PacketProcessor(receivedPacket); + break; +#endif +#ifdef CONFIG_MOUSE_ENABLED + case COMMAND_CLASS_HID_MOUSE: + Downstream_HID_PacketProcessor(receivedPacket); + break; +#endif +#ifdef CONFIG_KEYBOARD_ENABLED + case COMMAND_CLASS_HID_KEYBOARD: + Downstream_HID_PacketProcessor(receivedPacket); + break; +#endif + + //Add other classes here... + + default: + DOWNSTREAM_STATEMACHINE_FREAKOUT; + } +} + + + +//Used by downstream class interfaces, and SPI interface +void Downstream_PacketProcessor_FreakOut(void) +{ + DOWNSTREAM_STATEMACHINE_FREAKOUT; +} + + + +void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket) +{ + switch (receivedPacket->Command) + { + case COMMAND_INTERFACE_ECHO: + Downstream_TransmitPacket(receivedPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); + break; + + case COMMAND_INTERFACE_NOTIFY_DEVICE: + if (DownstreamState == STATE_DEVICE_READY) + { + Downstream_PacketProcessor_Interface_ReplyNotifyDevice(receivedPacket); + return; + } + + if (DownstreamState == STATE_DEVICE_NOT_READY) + { + DownstreamState = STATE_WAIT_DEVICE_READY; + Downstream_ReleasePacket(receivedPacket); + return; + } + DOWNSTREAM_STATEMACHINE_FREAKOUT; + break; + + + default: + DOWNSTREAM_STATEMACHINE_FREAKOUT; + } +} + + +void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket) +{ + replyPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16 + 1; + replyPacket->CommandClass = COMMAND_CLASS_INTERFACE; + replyPacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE; + replyPacket->Data[0] = ConfiguredDeviceClass; + + if (Downstream_TransmitPacket(replyPacket) == HAL_OK) + { + DownstreamState = STATE_ACTIVE; + Downstream_ReceivePacket(Downstream_PacketProcessor); + } +} + + +void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket) +{ + replyPacket->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + replyPacket->CommandClass = COMMAND_CLASS_ERROR; + replyPacket->Command = COMMAND_ERROR_GENERIC; + + Downstream_TransmitPacket(replyPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); + NotifyDisconnectReply = 0; +} + + +void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket) +{ + Downstream_TransmitPacket(replyPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); + NotifyDisconnectReply = 0; +} + + +void Downstream_PacketProcessor_NotifyDisconnectReplyRequired(void) +{ + NotifyDisconnectReply = 1; +} + + +void Downstream_PacketProcessor_CheckNotifyDisconnectReply(void) +{ + if (NotifyDisconnectReply == 2) + { + Downstream_GetFreePacket(Downstream_PacketProcessor_NotifyDisconnectReply); + } +} + + +void Downstream_PacketProcessor_NotifyDisconnectReply(DownstreamPacketTypeDef* packetToSend) +{ + packetToSend->Length16 = DOWNSTREAM_PACKET_HEADER_LEN_16; + packetToSend->CommandClass = COMMAND_CLASS_ERROR; + packetToSend->Command = COMMAND_ERROR_DEVICE_DISCONNECTED; + Downstream_PacketProcessor_ClassReply(packetToSend); +} + + +//This callback receives various event ids from the host stack, +//either at INT_PRIORITY_OTG_FS or from main(). +void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) +{ + InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE; + + if (DownstreamState >= STATE_ERROR) + { + return; + } + + //Called from USB interrupt. + //Simple function shouldn't need to worry about preempting anything important. + if (id == HOST_USER_DISCONNECTION) + { + DownstreamState = STATE_DEVICE_NOT_READY; + if (NotifyDisconnectReply == 1) + { + NotifyDisconnectReply = 2; //Request a 'device disconnected' reply when we get back to main() + } + return; + } + + + //Called from main() + if (id == HOST_USER_CLASS_ACTIVE) + { +#ifdef CONFIG_USB_ID_ENABLED + //check vendor product id + for(int i=0;idevice.DevDesc.idVendor && list[i].product==phost->device.DevDesc.idProduct){ + break; + }else{ + if(i==(USB_ID_COUNT-1)){//last usb device in list + DOWNSTREAM_STATEMACHINE_FREAKOUT; + } + } + } +#endif + + switch (phost->pActiveClass->ClassCode) + { +#ifdef CONFIG_MASS_STORAGE_ENABLED + case USB_MSC_CLASS: + newActiveClass = Downstream_MSC_ApproveConnectedDevice(); + break; +#endif +#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + case USB_HID_CLASS: + newActiveClass = Downstream_HID_ApproveConnectedDevice(); + break; +#endif + + //Add other classes here... + + + } + + //Unsupported device classes will cause a slow fault flash. + //This is distinct from the fast freakout flash caused by internal errors or attacks. + //We consider supported classes that fail their approval checks to also be unsupported devices. + if (newActiveClass == COMMAND_CLASS_INTERFACE) + { + USB_Host_Disconnect(); + LED_SetState(LED_STATUS_FLASH_UNSUPPORTED); + DownstreamState = STATE_ERROR; + return; + } + + //If we already configured a device class, we cannot change to a different one without rebooting. + //This blocks 'hidden device' BadUSB attacks. + if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) && + (ConfiguredDeviceClass != newActiveClass)) + { + DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; + } + ConfiguredDeviceClass = newActiveClass; + + if (DownstreamState == STATE_WAIT_DEVICE_READY) + { + Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice); + return; + } + + if (DownstreamState == STATE_DEVICE_NOT_READY) + { + DownstreamState = STATE_DEVICE_READY; + return; + } + + DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + + //Called from main(): + if ((id == HOST_USER_CLASS_FAILED) || + (id == HOST_USER_UNRECOVERED_ERROR)) //Probably due to a crappy device that won't enumerate! + { + //Unsupported device classes will cause a slow fault flash. + //This is distinct from the fast freakout flash caused by internal errors or attacks. + USB_Host_Disconnect(); + LED_SetState(LED_STATUS_FLASH_UNSUPPORTED); + DownstreamState = STATE_ERROR; + return; + } + +} + diff --git a/Downstream/Src/hal_msp.c b/Downstream/Src/hal_msp.c new file mode 100644 index 0000000..bf1608e --- /dev/null +++ b/Downstream/Src/hal_msp.c @@ -0,0 +1,163 @@ +/** + ****************************************************************************** + * File Name : stm32f4xx_hal_msp.c + * Description : This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "interrupts.h" +#include "board_config.h" + + +DMA_HandleTypeDef hdma_spi1_rx; +DMA_HandleTypeDef hdma_spi1_tx; + + + +void HAL_MspInit(void) +{ + + HAL_NVIC_SetPriority(SysTick_IRQn, INT_PRIORITY_SYSTICK, 0); +} + + +uint32_t HAL_GetHSECrystalFreqMHz(void) +{ + if ((BOARD_REV_ID_PORT->IDR & BOARD_REV_PIN_MASK) < BOARD_REV_1_0_BETA_3) + { + return BOARD_REV_1_0_BETA_FREQ; + } + else + { + return BOARD_REV_1_0_BETA_3_FREQ; + } +} + + +void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + if(hspi->Instance==SPI1) + { + __SPI1_CLK_ENABLE(); + __DMA2_CLK_ENABLE(); + + /**SPI1 GPIO Configuration + PA4 ------> SPI_NSS + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_4; //NSS is active low so pull up + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; + GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; //SCK & data are active high so pull down + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + UPSTREAM_TX_REQUEST_DEASSERT; + GPIO_InitStruct.Pin = UPSTREAM_TX_REQUEST_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UPSTREAM_TX_REQUEST_PORT, &GPIO_InitStruct); + + /* Peripheral DMA init*/ + hdma_spi1_rx.Instance = DMA2_Stream2; + hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3; + hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_spi1_rx.Init.Mode = DMA_NORMAL; + hdma_spi1_rx.Init.Priority = DMA_PRIORITY_MEDIUM; + hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_spi1_rx); + __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx); + + hdma_spi1_tx.Instance = DMA2_Stream3; + hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3; + hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_spi1_tx.Init.Mode = DMA_NORMAL; + hdma_spi1_tx.Init.Priority = DMA_PRIORITY_MEDIUM; + hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_spi1_tx); + __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx); + + /* DMA interrupt init */ + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, INT_PRIORITY_SPI_DMA, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); + HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, INT_PRIORITY_SPI_DMA, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); + + } +} + + +void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) +{ + + if(hspi->Instance==SPI1) + { + __SPI1_CLK_DISABLE(); + + /**SPI1 GPIO Configuration + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); + + /* Peripheral DMA DeInit*/ + HAL_DMA_DeInit(hspi->hdmarx); + HAL_DMA_DeInit(hspi->hdmatx); + } + +} + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Src/interrupts.c b/Downstream/Src/interrupts.c new file mode 100644 index 0000000..f7393fd --- /dev/null +++ b/Downstream/Src/interrupts.c @@ -0,0 +1,117 @@ +/** + ****************************************************************************** + * @file stm32f4xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "stm32f4xx.h" +#include "interrupts.h" +#include "led.h" +#include "board_config.h" + + +/* External variables --------------------------------------------------------*/ +extern HCD_HandleTypeDef hhcd_USB_OTG_FS; +extern DMA_HandleTypeDef hdma_spi1_rx; +extern DMA_HandleTypeDef hdma_spi1_tx; + +extern volatile uint8_t UsbInterruptHasHappened; + +uint8_t BusFaultAllowed = 0; + + +/******************************************************************************/ +/* Cortex-M4 Processor Interruption and Exception Handlers */ +/******************************************************************************/ + +/** +* @brief This function handles System tick timer. +*/ +void SysTick_Handler(void) +{ + HAL_IncTick(); + LED_Tick(); +} + +/******************************************************************************/ +/* STM32F4xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f4xx.s). */ +/******************************************************************************/ + + + +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_spi1_rx); +} + +void DMA2_Stream3_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_spi1_tx); +} + +void OTG_FS_IRQHandler(void) +{ + HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS); + UsbInterruptHasHappened = 1; +} + + +//This weird stuff is required when disabling flash writes. +//The deliberate flash lockout will cause a bus fault that we need to process. +void EnableOneBusFault(void) +{ + //It should not be enabled already! + if (BusFaultAllowed) + { + while (1); + } + SCB->SHCSR = SCB_SHCSR_BUSFAULTENA_Msk; + BusFaultAllowed = 1; +} + +void BusFault_Handler(void) +{ + if (BusFaultAllowed) + { + BusFaultAllowed = 0; + return; + } + while (1); +} + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Src/led.c b/Downstream/Src/led.c new file mode 100644 index 0000000..a6da5ac --- /dev/null +++ b/Downstream/Src/led.c @@ -0,0 +1,142 @@ +/* + * led.c + * + * Created on: 19/08/2015 + * Author: Robert Fisk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include "led.h" +#include "board_config.h" +#include "build_config.h" + +uint32_t FaultLedCounter; +uint32_t ReadWriteFlashEndTime; + +LedStatusTypeDef FaultLedState; +uint16_t FaultLedOnMs; +uint16_t FaultLedOffMs; +uint8_t FaultLedBlinkCount; + +uint8_t FaultLedBlinkCountState; +uint8_t FaultLedOutputState; + + +void LED_Init(void) +{ + FAULT_LED_ON; + ReadWriteFlashEndTime = 0; + FaultLedState = LED_STATUS_STARTUP; +} + + +void LED_SetState(LedStatusTypeDef newState) +{ + switch (newState) + { + case LED_STATUS_OFF: + FaultLedCounter = UINT32_MAX; + FaultLedBlinkCountState = 0; + FaultLedOutputState = 0; + FAULT_LED_OFF; + break; + + case LED_STATUS_FLASH_UNSUPPORTED: + FaultLedOnMs = LED_UNSUPPORTED_BLINK_MS; + FaultLedOffMs = LED_UNSUPPORTED_BLINK_MS; + FaultLedBlinkCount = 1; + break; + + case LED_STATUS_FLASH_BOTDETECT: + FaultLedOnMs = LED_BOTDETECT_ON_MS; + FaultLedOffMs = LED_BOTDETECT_OFF_MS; + FaultLedBlinkCount = 2; + break; + + case LED_STATUS_FLASH_READWRITE: +#ifdef CONFIG_READ_FLASH_TIME_MS + if (FaultLedState == LED_STATUS_OFF) + { + FaultLedOnMs = LED_READWRITE_ON_MS; + FaultLedOffMs = LED_READWRITE_OFF_MS; + FaultLedBlinkCount = 1; + ReadWriteFlashEndTime = HAL_GetTick() + CONFIG_READ_FLASH_TIME_MS; + } + else +#endif + { + newState = FaultLedState; //Don't override other active states + } + break; + + default: + FaultLedOnMs = LED_ERROR_BLINK_MS; //Everything else is LED_STATUS_ERROR + FaultLedOffMs = LED_ERROR_BLINK_MS; + FaultLedBlinkCount = 1; + } + + FaultLedState = newState; +} + + +void LED_Tick(void) +{ + if (FaultLedState == LED_STATUS_OFF) return; + + if (FaultLedState == LED_STATUS_STARTUP) + { + if (HAL_GetTick() >= STARTUP_FLASH_DELAY_MS) + { + LED_SetState(LED_STATUS_OFF); + } + return; + } + +#ifdef CONFIG_READ_FLASH_TIME_MS + if (FaultLedState == LED_STATUS_FLASH_READWRITE) + { + if ((int32_t)(HAL_GetTick() - ReadWriteFlashEndTime) > 0) + { + LED_SetState(LED_STATUS_OFF); + return; + } + } +#endif + + if (FaultLedOutputState) + { + if (FaultLedCounter++ >= FaultLedOnMs) //Check to turn LED off + { + FaultLedBlinkCountState++; + FaultLedCounter = 0; + FaultLedOutputState = 0; + FAULT_LED_OFF; + } + } + else + { + if (FaultLedBlinkCountState >= FaultLedBlinkCount) //Checks to turn LED on... + { + if (FaultLedCounter++ >= FaultLedOffMs) //Last flash may have longer off-time + { + FaultLedBlinkCountState = 0; + FaultLedCounter = 0; + FaultLedOutputState = 1; + FAULT_LED_ON; + } + } + else + { + if (FaultLedCounter++ >= FaultLedOnMs) //Flash sequence uses on-time as intermediate off-time + { + FaultLedCounter = 0; + FaultLedOutputState = 1; + FAULT_LED_ON; + } + } + } +} diff --git a/Downstream/Src/main.c b/Downstream/Src/main.c new file mode 100644 index 0000000..5ee813c --- /dev/null +++ b/Downstream/Src/main.c @@ -0,0 +1,286 @@ +/** + ****************************************************************************** + * File Name : main.c + * Description : Main program body + ****************************************************************************** + * + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "usb_host.h" +#include "board_config.h" +#include "downstream_statemachine.h" +#include "downstream_spi.h" +#include "led.h" +#include "interrupts.h" +#include "build_config.h" + + + +/* Private function prototypes -----------------------------------------------*/ +static void SystemClock_Config(void); +static void GPIO_Init(void); +static void DisableFlashWrites(void); +static void CheckFirmwareMatchesHardware(void); +static void SetRDPlevel(void); + +FLASH_OBProgramInitTypeDef flash_OBinit; + +volatile uint8_t UsbInterruptHasHappened = 0; +uint8_t IterationCount = 0; + + +int main(void) +{ + //First things first! +// DisableFlashWrites(); + CheckFirmwareMatchesHardware(); + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + +#ifdef CONFIG_FLASH_RDP_ENABLE + SetRDPlevel(); +#endif + + /* Configure the system clock */ + SystemClock_Config(); + + /* Initialize all configured peripherals */ + GPIO_Init(); + LED_Init(); + USB_Host_Init(); + + Downstream_InitStateMachine(); + + while (1) + { + USB_Host_Process(); + Downstream_SPIProcess(); + Downstream_PacketProcessor_CheckNotifyDisconnectReply(); + + //Count number of main loops since last USB interrupt + if (UsbInterruptHasHappened) + { + UsbInterruptHasHappened = 0; + IterationCount = 0; + } + + //Some USB host state transitions take 3 iterations to fully apply. + //We'll be generous and give it 5 before sleeping. + if (IterationCount++ > 4) + { + __WFI(); //sleep time! + } + } +} + + +void SetRDPlevel(void) +{ + HAL_FLASH_Unlock(); + HAL_FLASH_OB_Unlock(); + flash_OBinit.OptionType=OPTIONBYTE_RDP; + flash_OBinit.RDPLevel=OB_RDP_LEVEL_1; + HAL_FLASHEx_OBProgram(&flash_OBinit); + HAL_FLASH_OB_Launch(); + HAL_FLASH_OB_Lock(); + HAL_FLASH_Lock(); + +} + +void DisableFlashWrites(void) +{ + //Disable flash writes until the next reset + //This will cause a bus fault interrupt, so allow one now. + EnableOneBusFault(); + FLASH->KEYR = 999; + + //Confirm that flash cannot be unlocked + //This unlock attempt will also cause two bus faults. + if ((FLASH->CR & FLASH_CR_LOCK) == 0) while(1); + EnableOneBusFault(); + FLASH->KEYR = FLASH_KEY1; + EnableOneBusFault(); + FLASH->KEYR = FLASH_KEY2; + if ((FLASH->CR & FLASH_CR_LOCK) == 0) while(1); +} + + +void CheckFirmwareMatchesHardware(void) +{ + //Check we are running on the expected hardware: + //STM32F401RC on USG v1.0 beta + + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOB_CLK_ENABLE(); + + if ((*(uint32_t*)DBGMCU_BASE & DBGMCU_IDCODE_DEV_ID) == DBGMCU_IDCODE_DEV_ID_401xB_xC) + { + //Read in board revision and ID on port C + GPIO_InitStruct.Pin = BOARD_REV_PIN_MASK | BOARD_ID_PIN_MASK; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(BOARD_REV_ID_PORT, &GPIO_InitStruct); + + //Correct board revision? + if ((BOARD_REV_ID_PORT->IDR & BOARD_REV_PIN_MASK) <= BOARD_REV_1_0_BETA_3) + { + //Correct board ID: downstream? + if (!(BOARD_REV_ID_PORT->IDR & BOARD_ID_PIN_MASK)) + { + return; + } + } + } + + //This is not the hardware we expected, so turn on our fault LED(s) and die in a heap. + GPIO_InitStruct.Pin = FAULT_LED_PIN | H405_FAULT_LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(FAULT_LED_PORT, &GPIO_InitStruct); + FAULT_LED_ON; + H405_FAULT_LED_ON; + while (1); +} + + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + + __PWR_CLK_ENABLE(); + + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = (HAL_GetHSECrystalFreqMHz() / 2); //PLL input frequency = 2MHz + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; + RCC_OscInitStruct.PLL.PLLQ = 7; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) while (1); + + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | + RCC_CLOCKTYPE_HCLK | + RCC_CLOCKTYPE_PCLK1 | + RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) while (1); + + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + + + + +void GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + + /* GPIO Ports Clock Enable */ + //__GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + //Bulk initialise all ports as inputs with pullups active, + //excluding JTAG pins which must remain as AF0! + GPIO_InitStruct.Pin = (GPIO_PIN_All & ~(PA_JTMS | PA_JTCK | PA_JTDI)); + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitStruct.Pin = (GPIO_PIN_All & ~(PB_JTDO | PB_NJTRST)); + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + GPIO_InitStruct.Pin = GPIO_PIN_All; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + //Fault LED is output + GPIO_InitStruct.Pin = FAULT_LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(FAULT_LED_PORT, &GPIO_InitStruct); + FAULT_LED_OFF; + +// //SPI_INT_ACTIVE indicator +// GPIO_InitStruct.Pin = INT_ACTIVE_PIN; +// HAL_GPIO_Init(INT_ACTIVE_PORT, &GPIO_InitStruct); +// INT_ACTIVE_OFF; +} + + + +#ifdef USE_FULL_ASSERT + +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ + +} + +#endif + +/** + * @} + */ + +/** + * @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Src/usb_host.c b/Downstream/Src/usb_host.c new file mode 100644 index 0000000..694d3d8 --- /dev/null +++ b/Downstream/Src/usb_host.c @@ -0,0 +1,88 @@ +/** + ****************************************************************************** + * @file : USB_HOST + * @version : v1.0_Cube + * @brief : This file implements the USB Host + ****************************************************************************** + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_host.h" +#include "usbh_core.h" +#include "usbh_msc.h" +#include "usbh_hid.h" +#include "downstream_statemachine.h" +#include "build_config.h" + + +/* USB Host Core handle declaration */ +USBH_HandleTypeDef hUsbHostFS; + + +/* init function */ +void USB_Host_Init(void) +{ + /* Init Host Library,Add Supported Class and Start the library*/ + USBH_Init(&hUsbHostFS, Downstream_HostUserCallback, HOST_FS); + +#ifdef CONFIG_MASS_STORAGE_ENABLED + USBH_RegisterClass(&hUsbHostFS, USBH_MSC_CLASS); +#endif +#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED) + USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS); +#endif + + USBH_Start(&hUsbHostFS); +} + +/* + * Background task +*/ +void USB_Host_Process() +{ + /* USB Host Background task */ + USBH_Process(&hUsbHostFS); + +} + + +//Called when Downstream Statemachine or SPI freaks out. +void USB_Host_Disconnect() +{ + USBH_DeInit(&hUsbHostFS); +} + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/Src/usbh_config.c b/Downstream/Src/usbh_config.c new file mode 100644 index 0000000..4d842f0 --- /dev/null +++ b/Downstream/Src/usbh_config.c @@ -0,0 +1,470 @@ +/** + ****************************************************************************** + * @file : usbh_conf.c + * @version : v1.0_Cube + * @brief : This file implements the board support package for the USB host library + ****************************************************************************** + * COPYRIGHT(c) 2015 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * Modifications by Robert Fisk + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "interrupts.h" + + +HCD_HandleTypeDef hhcd_USB_OTG_FS; + + +/******************************************************************************* + LL Driver Callbacks (HCD -> USB Host Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + if(hhcd->Instance==USB_OTG_FS) + { + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __USB_OTG_FS_CLK_ENABLE(); + + /* Peripheral interrupt init*/ + HAL_NVIC_SetPriority(OTG_FS_IRQn, INT_PRIORITY_USB, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hhcd) +{ + if(hhcd->Instance==USB_OTG_FS) + { + /* Peripheral clock disable */ + __USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA9 ------> USB_OTG_FS_VBUS + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + //HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + } +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_IncTimer (hhcd->pData); +} + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_Connect(hhcd->pData); +} + + +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + USBH_LL_PortEnabled(hhcd->pData); +} + + +/** + * @brief SOF callback. + * @param hhcd: HCD handle + * @retval None + */ +HAL_StatusTypeDef HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + if (USBH_LL_Disconnect(hhcd->pData) == USBH_OK) + { + return HAL_OK; + } + return HAL_ERROR; +} + +/** + * @brief Notify URB state change callback. + * @param hhcd: HCD handle + * @retval None + */ +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* To be used with OS to sync URB state with the global state machine */ +#if (USBH_USE_OS == 1) + USBH_LL_NotifyURBChange(hhcd->pData); +#endif +} +/******************************************************************************* + LL Driver Interface (USB Host Library --> HCD) +*******************************************************************************/ +/** + * @brief USBH_LL_Init + * Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost) +{ + /* Init USB_IP */ + if (phost->id == HOST_FS) { + /* Link The driver to the stack */ + hhcd_USB_OTG_FS.pData = phost; + phost->pData = &hhcd_USB_OTG_FS; + + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + HAL_HCD_Init(&hhcd_USB_OTG_FS); + + USBH_LL_SetTimer (phost, HAL_HCD_GetCurrentFrame(&hhcd_USB_OTG_FS)); + } + return USBH_OK; +} + +/** + * @brief USBH_LL_DeInit + * De-Initialize the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost) +{ + HAL_HCD_DeInit(phost->pData); + return USBH_OK; +} + +/** + * @brief USBH_LL_Start + * Start the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) +{ + HAL_HCD_Start(phost->pData); + return USBH_OK; +} + +/** + * @brief USBH_LL_Stop + * Stop the Low Level portion of the Host driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost) +{ + HAL_HCD_Stop(phost->pData); + return USBH_OK; +} + +/** + * @brief USBH_LL_GetSpeed + * Return the USB Host Speed from the Low Level Driver. + * @param phost: Host handle + * @retval USBH Speeds + */ +USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost) +{ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)) + { + case 0 : + speed = USBH_SPEED_HIGH; + break; + +// case 1 : +// speed = USBH_SPEED_FULL; +// break; + + case 2 : + speed = USBH_SPEED_LOW; + break; + +// default: +// speed = USBH_SPEED_FULL; +// break; + } + return speed; +} + +/** + * @brief USBH_LL_ResetPort + * Reset the Host Port of the Low Level Driver. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost) +{ + HAL_HCD_ResetPort(phost->pData); + return USBH_OK; +} + +/** + * @brief USBH_LL_GetLastXferSize + * Return the last transfered packet size. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval Packet Size + */ +uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief USBH_LL_OpenPipe + * Open a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @param epnum: Endpoint Number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint Type + * @param mps: Endpoint Max Packet Size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, + uint8_t pipe_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + HAL_HCD_HC_Init(phost->pData, + pipe_num, + epnum, + dev_address, + speed, + ep_type, + mps); + return USBH_OK; +} + +/** + * @brief USBH_LL_ClosePipe + * Close a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe_num: Pipe index + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_HCD_HC_Halt(phost->pData, pipe); + return USBH_OK; +} + +/** + * @brief USBH_LL_SubmitURB + * Submit a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction : Channel number + * This parameter can be one of the these values: + * 0 : Output + * 1 : Input + * @param ep_type : Endpoint Type + * This parameter can be one of the these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochrounous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token : Endpoint Type + * This parameter can be one of the these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff : pointer to URB data + * @param length : Length of URB data + * @param do_ping : activate do ping protocol (for high speed only) + * This parameter can be one of the these values: + * 0 : do ping inactive + * 1 : do ping active + * @retval Status + */ + +USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping ) +{ + HAL_HCD_HC_SubmitRequest (phost->pData, + pipe, + direction , + ep_type, + token, + pbuff, + length, + do_ping); + return USBH_OK; +} + +/** + * @brief USBH_LL_GetURBState + * Get a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of the these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief USBH_LL_DriverVBUS + * Drive VBUS. + * @param phost: Host handle + * @param state : VBUS state + * This parameter can be one of the these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state) +{ + //Our VBUS is permanently on, so don't bother with this... + +// if (phost->id == HOST_FS) +// { +// if(state == 0) +// { +// //VBUS off +// } +// else +// { +// //VBUS on +// } +// } +// HAL_Delay(200); + return USBH_OK; +} + +/** + * @brief USBH_LL_SetToggle + * Set toggle for a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @param pipe_num: Pipe index + * @param toggle: toggle (0/1) + * @retval Status + */ +USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) +{ + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + pHandle->hc[pipe].toggle_in = toggle; + } + else + { + pHandle->hc[pipe].toggle_out = toggle; + } + + return USBH_OK; +} + +/** + * @brief USBH_LL_GetToggle + * Return the current toggle of a pipe. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval toggle (0/1) + */ +uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe) +{ + uint8_t toggle = 0; + HCD_HandleTypeDef *pHandle; + pHandle = phost->pData; + + if(pHandle->hc[pipe].ep_is_in) + { + toggle = pHandle->hc[pipe].toggle_in; + } + else + { + toggle = pHandle->hc[pipe].toggle_out; + } + return toggle; +} + +/** + * @brief USBH_Delay + * Delay routine for the USB Host Library + * @param Delay: Delay in ms + * @retval None + */ +void USBH_Delay (uint32_t Delay) +{ + HAL_Delay(Delay); +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Downstream/gcc_arm_stm32f401.ld b/Downstream/gcc_arm_stm32f401.ld new file mode 100644 index 0000000..0fffc55 --- /dev/null +++ b/Downstream/gcc_arm_stm32f401.ld @@ -0,0 +1,115 @@ +/* Linker script to configure memory regions. */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K + SRAM1 (xrw) : ORIGIN = 0x20000000, LENGTH = 64K + +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + /* All data end */ + __data_end__ = .; + + } > SRAM1 + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > SRAM1 + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > SRAM1 + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + KEEP(*(.stack*)) + } > SRAM1 + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(SRAM1) + LENGTH(SRAM1); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + +}