USG firmware update

master
Ivan Olenichev 3 years ago
parent 7a8206f026
commit e527810411

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800" name="Debug" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postbuildStep="${cross_prefix}objcopy -O binary ${ProjName}.${BuildArtifactFileExt} ${ProjName}.bin">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800." name="/" resourcePath="">
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.1271795031" name="Cross ARM GCC" nonInternalBuilderId="ilg.gnuarmeclipse.managedbuild.cross.builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.2140590766" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.debug" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.1655246483" name="Message length (-fmessage-length=0)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.1912399695" name="'char' is signed (-fsigned-char)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.2097677227" name="Function sections (-ffunction-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.1364848851" name="Data sections (-fdata-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.728815383" name="Debug level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.max" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.973313256" name="Debug format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format" useByScannerDiscovery="true"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.859574207" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name" useByScannerDiscovery="false" value="GNU Tools for ARM Embedded Processors" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.1378373916" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1657788080" name="ARM family" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.mcpu.cortex-m4" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.21974397" name="Instruction set" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.thumb" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.195914210" name="Prefix" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.1353241937" name="C compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.c" useByScannerDiscovery="false" value="gcc" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.935285285" name="C++ compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp" useByScannerDiscovery="false" value="g++" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.799920162" name="Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar" useByScannerDiscovery="false" value="ar" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.495282384" name="Hex/Bin converter" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy" useByScannerDiscovery="false" value="objcopy" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.687084139" name="Listing generator" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump" useByScannerDiscovery="false" value="objdump" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.760453142" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size" useByScannerDiscovery="false" value="size" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.539315105" name="Build command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make" useByScannerDiscovery="false" value="make" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.751122475" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm" useByScannerDiscovery="false" value="rm" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.1606753881" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.1592639420" name="Print size" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized.1570781551" name="Warn on uninitialized variables (-Wuninitialised)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.unused.405290154" name="Warn on various unused elements (-Wunused)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.unused" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.allwarn.2061379866" name="Enable all common warnings (-Wall)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.allwarn" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.extrawarn.235340212" name="Enable extra warnings (-Wextra)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.extrawarn" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.conversion.19359341" name="Warn on implicit conversions (-Wconversion)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.conversion" useByScannerDiscovery="true" value="false" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop.1966851850" name="Warn if suspicious logical ops (-Wlogical-op)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith.1529172556" name="Warn if pointer arithmetic (-Wpointer-arith)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.481456479" name="Float ABI" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.hard" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.2034326975" name="FPU Type" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.fpv4spd16" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id.1727424018" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id" useByScannerDiscovery="false" value="1287942917" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform.1042769951" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/>
<builder buildPath="${workspace_loc:/Downstream}/Debug" id="ilg.gnuarmeclipse.managedbuild.cross.builder.2070257479" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="ilg.gnuarmeclipse.managedbuild.cross.builder"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.789837881" name="Cross ARM GNU Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor.1524992420" name="Use preprocessor" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.defs.559716966" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F401xC"/>
</option>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input.1659311775" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1693581131" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths.822026556" name="Include paths (-I)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/STM32F4xx_HAL_Driver/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/CMSIS/Device/ST/STM32F4xx/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/CMSIS/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.914524327" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F401xC"/>
</option>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.1745725913" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.1707231517" name="Cross ARM C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.254208823" name="Cross ARM C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections.19615684" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnano.1093194778" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostart.1226941524" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile.2018055305" name="Script files (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/gcc_arm_stm32f401.ld}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnosys.473764979" name="Do not use syscalls (--specs=nosys.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnosys" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input.1124786404" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.975001742" name="Cross ARM C++ Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections.2071573630" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano.533761955" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile.2117286361" name="Script files (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/gcc_arm_stm32f401.ld}&quot;"/>
</option>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.2092748559" name="Cross ARM GNU Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.2147256520" name="Cross ARM GNU Create Flash Image" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.952474437" name="Cross ARM GNU Create Listing" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source.1884468527" name="Display source (--source|-S)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders.1480743382" name="Display all headers (--all-headers|-x)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle.1214841688" name="Demangle names (--demangle|-C)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers.186728271" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide.409648956" name="Wide lines (--wide|-w)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.2134899522" name="Cross ARM GNU Print Size" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format.596374317" name="Size format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format" useByScannerDiscovery="false"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.totals.878347212" name="Show totals" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.totals" useByScannerDiscovery="false" value="false" valueType="boolean"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_keybd.c|Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_mouse.c|Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_parser.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c|Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_conf_template.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnuarmeclipse.managedbuild.packs">
<option id="cmsis.device.name" value="STM32F401RC"/>
<option id="cmsis.subfamily.name" value="STM32F401"/>
<option id="cmsis.family.name" value="STM32F4 Series"/>
<option id="cmsis.device.vendor.name" value="STMicroelectronics"/>
<option id="cmsis.device.vendor.id" value="13"/>
<option id="cmsis.device.pack.vendor" value="Keil"/>
<option id="cmsis.device.pack.name" value="STM32F4xx_DFP"/>
<option id="cmsis.device.pack.version" value="2.4.0"/>
<option id="cmsis.core.name" value="Cortex-M4"/>
<option id="cmsis.compiler.define" value="STM32F401xC"/>
<memory section="IRAM1" size="0x10000" start="0x20000000" startup="0"/>
<memory section="IROM1" size="0x40000" start="0x08000000" startup="1"/>
</storageModule>
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs">
<option id="cmsis.device.name" value="STM32F401RB"/>
<option id="cmsis.subfamily.name" value="STM32F401"/>
<option id="cmsis.family.name" value="STM32F4 Series"/>
<option id="cmsis.device.vendor.name" value="STMicroelectronics"/>
<option id="cmsis.device.vendor.id" value="13"/>
<option id="cmsis.device.pack.vendor" value="Keil"/>
<option id="cmsis.device.pack.name" value="STM32F4xx_DFP"/>
<option id="cmsis.device.pack.version" value="2.11.0"/>
<option id="cmsis.core.name" value="Cortex-M4"/>
<option id="cmsis.compiler.define" value="STM32F401xC"/>
<memory section="IRAM1" size="0x10000" start="0x20000000" startup="0"/>
<memory section="IROM1" size="0x20000" start="0x08000000" startup="1"/>
</storageModule>
</cconfiguration>
<cconfiguration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207" name="Release" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release" postbuildStep="${cross_prefix}objcopy -O binary ${ProjName}.${BuildArtifactFileExt} ${ProjName}.bin">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207." name="/" resourcePath="">
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.release.14803562" name="Cross ARM GCC" nonInternalBuilderId="ilg.gnuarmeclipse.managedbuild.cross.builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.release">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.900298893" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.most" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.1083811839" name="Message length (-fmessage-length=0)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.1983172660" name="'char' is signed (-fsigned-char)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.413875025" name="Function sections (-ffunction-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.797056914" name="Data sections (-fdata-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.1607820960" name="Debug level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level" useByScannerDiscovery="true"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.753446064" name="Debug format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format" useByScannerDiscovery="true"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.871783047" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name" useByScannerDiscovery="false" value="GNU Tools for ARM Embedded Processors" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.980964112" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1722001019" name="ARM family" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.mcpu.cortex-m4" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.311057983" name="Instruction set" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.thumb" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.985310446" name="Prefix" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.2064369703" name="C compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.c" useByScannerDiscovery="false" value="gcc" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.2113985058" name="C++ compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp" useByScannerDiscovery="false" value="g++" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.492854105" name="Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar" useByScannerDiscovery="false" value="ar" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.1405530795" name="Hex/Bin converter" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy" useByScannerDiscovery="false" value="objcopy" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.674464443" name="Listing generator" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump" useByScannerDiscovery="false" value="objdump" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.733095594" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size" useByScannerDiscovery="false" value="size" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.1656691734" name="Build command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make" useByScannerDiscovery="false" value="make" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.969460679" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm" useByScannerDiscovery="false" value="rm" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.345738649" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.2110677739" name="Print size" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.unused.507402152" name="Warn on various unused elements (-Wunused)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.unused" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized.711919668" name="Warn on uninitialized variables (-Wuninitialised)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.allwarn.144133984" name="Enable all common warnings (-Wall)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.allwarn" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.extrawarn.1473585294" name="Enable extra warnings (-Wextra)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.extrawarn" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith.1192110404" name="Warn if pointer arithmetic (-Wpointer-arith)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop.322411367" name="Warn if suspicious logical ops (-Wlogical-op)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.1624213557" name="Float ABI" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.hard" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.1977148493" name="FPU Type" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.fpv4spd16" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id.993230501" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id" useByScannerDiscovery="false" value="1287942917" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform.777514892" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/>
<builder buildPath="${workspace_loc:/Downstream}/Release" id="ilg.gnuarmeclipse.managedbuild.cross.builder.1006388187" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="ilg.gnuarmeclipse.managedbuild.cross.builder"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.314526004" name="Cross ARM GNU Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor.2143421487" name="Use preprocessor" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.defs.1659712048" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F401xC"/>
</option>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input.2143048963" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.464951680" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths.1491964591" name="Include paths (-I)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/STM32F4xx_HAL_Driver/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/CMSIS/Device/ST/STM32F4xx/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Drivers/CMSIS/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Core/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Inc}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.569825136" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F401xC"/>
</option>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.37132336" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.118177754" name="Cross ARM C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.517364889" name="Cross ARM C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections.961434630" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostart.655825353" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile.773899963" name="Script files (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/gcc_arm_stm32f401.ld}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnano.1318058184" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnosys.1401331857" name="Do not use syscalls (--specs=nosys.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.usenewlibnosys" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input.447256356" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.426760484" name="Cross ARM C++ Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections.880923175" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano.464992520" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile.1888266216" name="Script files (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/gcc_arm_stm32f401.ld}&quot;"/>
</option>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.1866465855" name="Cross ARM GNU Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.1030031530" name="Cross ARM GNU Create Flash Image" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.1578819914" name="Cross ARM GNU Create Listing" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source.1760059993" name="Display source (--source|-S)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders.776514180" name="Display all headers (--all-headers|-x)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle.1214988650" name="Demangle names (--demangle|-C)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers.2091080948" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide.320970754" name="Wide lines (--wide|-w)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.1434556593" name="Cross ARM GNU Print Size" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format.1187784576" name="Size format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format" useByScannerDiscovery="false"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_keybd.c|Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_mouse.c|Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid_parser.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c|Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_conf_template.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c|Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnuarmeclipse.managedbuild.packs">
<option id="cmsis.device.name" value="STM32F401RC"/>
<option id="cmsis.subfamily.name" value="STM32F401"/>
<option id="cmsis.family.name" value="STM32F4 Series"/>
<option id="cmsis.device.vendor.name" value="STMicroelectronics"/>
<option id="cmsis.device.vendor.id" value="13"/>
<option id="cmsis.device.pack.vendor" value="Keil"/>
<option id="cmsis.device.pack.name" value="STM32F4xx_DFP"/>
<option id="cmsis.device.pack.version" value="2.4.0"/>
<option id="cmsis.core.name" value="Cortex-M4"/>
<option id="cmsis.compiler.define" value="STM32F401xC"/>
<memory section="IRAM1" size="0x10000" start="0x20000000" startup="0"/>
<memory section="IROM1" size="0x40000" start="0x08000000" startup="1"/>
</storageModule>
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs">
<option id="cmsis.device.name" value="STM32F401RB"/>
<option id="cmsis.subfamily.name" value="STM32F401"/>
<option id="cmsis.family.name" value="STM32F4 Series"/>
<option id="cmsis.device.vendor.name" value="STMicroelectronics"/>
<option id="cmsis.device.vendor.id" value="13"/>
<option id="cmsis.device.pack.vendor" value="Keil"/>
<option id="cmsis.device.pack.name" value="STM32F4xx_DFP"/>
<option id="cmsis.device.pack.version" value="2.11.0"/>
<option id="cmsis.core.name" value="Cortex-M4"/>
<option id="cmsis.compiler.define" value="STM32F401xC"/>
<memory section="IRAM1" size="0x10000" start="0x20000000" startup="0"/>
<memory section="IROM1" size="0x20000" start="0x08000000" startup="1"/>
</storageModule>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="Downstream.ilg.gnuarmeclipse.managedbuild.cross.target.elf.1348817548" name="Executable" projectType="ilg.gnuarmeclipse.managedbuild.cross.target.elf"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800;ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800.;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1693581131;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.1745725913">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207;ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207.;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.464951680;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.37132336">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/Downstream"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/Downstream"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>

@ -0,0 +1,2 @@
/Debug/
/Release/

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Downstream</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1119754748549797289" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
<configuration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1102788320777581571" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

@ -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}}

@ -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

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="ilg.gnumcueclipse.debug.gdbjtag.openocd.launchConfigurationType">
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doContinue" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateConsole" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateTelnetConsole" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doSecondReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbCLient" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbServer" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.enableSemihosting" value="true"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.firstResetType" value="init"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherCommands" value="set mem inaccessible-by-default off"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherOptions" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerConnectionAddress" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerExecutable" value="${openocd_path}/${openocd_executable}"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerGdbPortNumber" value="3333"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerLog" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerOther" value="-f interface/stlink.cfg -f ../OpenOCD_scripts/board/OpenOCD_USG_v1.0.cfg"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTclPortNumber" value="6666"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTelnetPortNumber" value="4444"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherInitCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherRunCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.secondResetType" value="halt"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.svdPath" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="GNU MCU OpenOCD"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="/home/antonlysak/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gdb"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Debug/Downstream.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="Downstream"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Downstream"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;Context string&quot;/&gt;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="ilg.gnumcueclipse.debug.gdbjtag.openocd.launchConfigurationType">
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doContinue" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateConsole" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateTelnetConsole" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doSecondReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbCLient" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbServer" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.enableSemihosting" value="true"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.firstResetType" value="init"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherCommands" value="set mem inaccessible-by-default off"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherOptions" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerConnectionAddress" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerExecutable" value="${openocd_path}/${openocd_executable}"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerGdbPortNumber" value="3333"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerLog" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerOther" value="-f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f ../OpenOCD_scripts/board/OpenOCD_USG_v1.0.cfg"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTclPortNumber" value="6666"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTelnetPortNumber" value="4444"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherInitCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherRunCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.secondResetType" value="halt"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.svdPath" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="GNU MCU OpenOCD"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="${cross_prefix}gdb${cross_suffix}"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Debug/Downstream.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="Downstream"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.110983800"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Downstream"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;Context string&quot;/&gt;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="ilg.gnumcueclipse.debug.gdbjtag.openocd.launchConfigurationType">
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doContinue" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doDebugInRam" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doFirstReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateConsole" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doGdbServerAllocateTelnetConsole" value="false"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doSecondReset" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbCLient" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.doStartGdbServer" value="true"/>
<booleanAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.enableSemihosting" value="true"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.firstResetType" value="init"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherCommands" value="set mem inaccessible-by-default off"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbClientOtherOptions" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerConnectionAddress" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerExecutable" value="${openocd_path}/${openocd_executable}"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerGdbPortNumber" value="3333"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerLog" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerOther" value="-f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f ../OpenOCD_scripts/board/OpenOCD_USG_v1.0.cfg"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTclPortNumber" value="6666"/>
<intAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.gdbServerTelnetPortNumber" value="4444"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherInitCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.otherRunCommands" value=""/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.openocd.secondResetType" value="halt"/>
<stringAttribute key="ilg.gnumcueclipse.debug.gdbjtag.svdPath" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="GNU MCU OpenOCD"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="${cross_prefix}gdb${cross_suffix}"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Release/Downstream.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="Downstream"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1300395207"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Downstream"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;Context string&quot;/&gt;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

@ -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_ */

@ -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_ */

@ -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_ */

@ -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_ */

@ -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_ */

@ -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_ */

@ -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_ */

@ -0,0 +1,423 @@
/**
******************************************************************************
* @file stm32f4xx_hal_conf.h
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* 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****/

@ -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****/

@ -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_ */

@ -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****/

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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****/

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_PIPES_H
#define __USBH_PIPES_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_PIPES
* @brief This file is the header file for usbh_pipes.c
* @{
*/
/** @defgroup USBH_PIPES_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t ch_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num);
uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost,
uint8_t ep_addr);
USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost,
uint8_t idx);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_PIPES_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,271 @@
/**
******************************************************************************
* @file usb_bsp.c
* @author MCD Application Team
* @version V3.2.1
* @date 26-June-2015
* @brief This file implements the board support package for the USB host library
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/**
* @brief USBH_LL_Init
* Initialize the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_DeInit
* De-Initialize the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_Start
* Start the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_Stop
* Stop the Low Level portion of the Host driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetSpeed
* Return the USB Host Speed from the Low Level Driver.
* @param phost: Host handle
* @retval USBH Speeds
*/
USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost)
{
USBH_SpeedTypeDef speed = USBH_SPEED_FULL;
return speed;
}
/**
* @brief USBH_LL_ResetPort
* Reset the Host Port of the Low Level Driver.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetLastXferSize
* Return the last transferred packet size.
* @param phost: Host handle
* @param pipe: Pipe index
* @retval Packet Size
*/
uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return 0;
}
/**
* @brief USBH_LL_OpenPipe
* Open a pipe of the Low Level Driver.
* @param phost: Host handle
* @param pipe_num: Pipe index
* @param epnum: Endpoint Number
* @param dev_address: Device USB address
* @param speed: Device Speed
* @param ep_type: Endpoint Type
* @param mps: Endpoint Max Packet Size
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
return USBH_OK;
}
/**
* @brief USBH_LL_ClosePipe
* Close a pipe of the Low Level Driver.
* @param phost: Host handle
* @param pipe_num: Pipe index
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return USBH_OK;
}
/**
* @brief USBH_LL_SubmitURB
* Submit a new URB to the low level driver.
* @param phost: Host handle
* @param pipe: Pipe index
* This parameter can be a value from 1 to 15
* @param direction : Channel number
* This parameter can be one of the these values:
* 0 : Output
* 1 : Input
* @param ep_type : Endpoint Type
* This parameter can be one of the these values:
* @arg EP_TYPE_CTRL: Control type
* @arg EP_TYPE_ISOC: Isochronous type
* @arg EP_TYPE_BULK: Bulk type
* @arg EP_TYPE_INTR: Interrupt type
* @param token : Endpoint Type
* This parameter can be one of the these values:
* @arg 0: PID_SETUP
* @arg 1: PID_DATA
* @param pbuff : pointer to URB data
* @param length : Length of URB data
* @param do_ping : activate do ping protocol (for high speed only)
* This parameter can be one of the these values:
* 0 : do ping inactive
* 1 : do ping active
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost,
uint8_t pipe,
uint8_t direction ,
uint8_t ep_type,
uint8_t token,
uint8_t* pbuff,
uint16_t length,
uint8_t do_ping )
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetURBState
* Get a URB state from the low level driver.
* @param phost: Host handle
* @param pipe: Pipe index
* This parameter can be a value from 1 to 15
* @retval URB state
* This parameter can be one of the these values:
* @arg URB_IDLE
* @arg URB_DONE
* @arg URB_NOTREADY
* @arg URB_NYET
* @arg URB_ERROR
* @arg URB_STALL
*/
USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe)
{
return USBH_URB_IDLE;
}
/**
* @brief USBH_LL_DriverVBUS
* Drive VBUS.
* @param phost: Host handle
* @param state : VBUS state
* This parameter can be one of the these values:
* 0 : VBUS Active
* 1 : VBUS Inactive
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state)
{
return USBH_OK;
}
/**
* @brief USBH_LL_SetToggle
* Set toggle for a pipe.
* @param phost: Host handle
* @param pipe: Pipe index
* @param pipe_num: Pipe index
* @param toggle: toggle (0/1)
* @retval Status
*/
USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle)
{
return USBH_OK;
}
/**
* @brief USBH_LL_GetToggle
* Return the current toggle of a pipe.
* @param phost: Host handle
* @param pipe: Pipe index
* @retval toggle (0/1)
*/
uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe)
{
uint8_t toggle = 0;
return toggle;
}
/**
* @brief USBH_Delay
* Delay routine for the USB Host Library
* @param Delay: Delay in ms
* @retval None
*/
void USBH_Delay (uint32_t Delay)
{
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

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

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

@ -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
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_ioreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_IOREQ
* @brief This file handles the standard protocol processing (USB v2.0)
* @{
*/
/** @defgroup USBH_IOREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Functions
* @{
*/
/**
* @brief USBH_CtlSendSetup
* Sends the Setup Packet to the Device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be send to Device
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_CONTROL, /* EP type */
USBH_PID_SETUP, /* Type setup */
buff, /* data buffer */
USBH_SETUP_PKT_SIZE, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_CtlSendData
* Sends a data Packet to the Device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be sent to Device
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num,
uint8_t do_ping )
{
if(phost->device.speed != USBH_SPEED_HIGH)
{
do_ping = 0;
}
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_CONTROL, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
do_ping); /* do ping (HS Only)*/
return USBH_OK;
}
/**
* @brief USBH_CtlReceiveData
* Receives the Device Response to the Setup Packet
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost,
uint8_t* buff,
uint16_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_CONTROL, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_BulkSendData
* Sends the Bulk Packet to the device
* @param phost: Host Handle
* @param buff: Buffer pointer from which the Data will be sent to Device
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num,
uint8_t do_ping )
{
if(phost->device.speed != USBH_SPEED_HIGH)
{
do_ping = 0;
}
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : IN */
USBH_EP_BULK, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
do_ping); /* do ping (HS Only)*/
return USBH_OK;
}
/**
* @brief USBH_BulkReceiveData
* Receives IN bulk packet from device
* @param phost: Host Handle
* @param buff: Buffer pointer in which the received data packet to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint16_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_BULK, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_InterruptReceiveData
* Receives the Device Response to the Interrupt IN token
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_INTERRUPT, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_InterruptSendData
* Sends the data on Interrupt OUT Endpoint
* @param phost: Host Handle
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint8_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_INTERRUPT, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_IsocReceiveData
* Receives the Device Response to the Isochronous IN token
* @param phost: Host Handle
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
1, /* Direction : IN */
USBH_EP_ISO, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @brief USBH_IsocSendData
* Sends the data on Isochronous OUT Endpoint
* @param phost: Host Handle
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param pipe_num: Pipe Number
* @retval USBH Status.
*/
USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost,
uint8_t *buff,
uint32_t length,
uint8_t pipe_num)
{
USBH_LL_SubmitURB (phost, /* Driver handle */
pipe_num, /* Pipe index */
0, /* Direction : OUT */
USBH_EP_ISO, /* EP type */
USBH_PID_DATA, /* Type Data */
buff, /* data buffer */
length, /* data length */
0);
return USBH_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,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
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_pipes.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_PIPES
* @brief This file includes opening and closing Pipes
* @{
*/
/** @defgroup USBH_PIPES_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_PIPES_Private_Functions
* @{
*/
static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost);
/**
* @brief USBH_Open_Pipe
* Open a pipe
* @param phost: Host Handle
* @param pipe_num: Pipe Number
* @param dev_address: USB Device address allocated to attached device
* @param speed : USB device speed (Full/Low)
* @param ep_type: end point type (Bulk/int/ctl)
* @param mps: max pkt size
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num,
uint8_t epnum,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
USBH_LL_OpenPipe(phost,
pipe_num,
epnum,
dev_address,
speed,
ep_type,
mps);
return USBH_OK;
}
/**
* @brief USBH_ClosePipe
* Close a pipe
* @param phost: Host Handle
* @param pipe_num: Pipe Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost,
uint8_t pipe_num)
{
USBH_LL_ClosePipe(phost, pipe_num);
return USBH_OK;
}
/**
* @brief USBH_Alloc_Pipe
* Allocate a new Pipe
* @param phost: Host Handle
* @param ep_addr: End point for which the Pipe to be allocated
* @retval Pipe number
*/
uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr)
{
uint16_t pipe;
pipe = USBH_GetFreePipe(phost);
if (pipe != 0xFFFF)
{
phost->Pipes[pipe] = 0x8000 | ep_addr;
}
return pipe;
}
/**
* @brief USBH_Free_Pipe
* Free the USB Pipe
* @param phost: Host Handle
* @param idx: Pipe number to be freed
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx)
{
if (idx < 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****/

@ -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)

@ -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

@ -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;
}

@ -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;i<USB_ID_COUNT;i++){
if(list[i].vendor==phost->device.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;
}
}

@ -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****/

@ -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****/

@ -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;
}
}
}
}

@ -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****/

@ -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****/

@ -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****/

@ -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")
}
Loading…
Cancel
Save