Initial import
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
bin
|
||||
debug
|
||||
dep
|
||||
obj
|
||||
src/u2f_crypto_data.h
|
||||
|
||||
|
||||
170
Makefile.daosend
Executable file
170
Makefile.daosend
Executable file
@@ -0,0 +1,170 @@
|
||||
#*******************************************************************************
|
||||
# Ledger Blue
|
||||
# (c) 2016 Ledger
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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.
|
||||
#*******************************************************************************
|
||||
|
||||
APPNAME = DAOSND
|
||||
|
||||
|
||||
################
|
||||
# Default rule #
|
||||
################
|
||||
|
||||
all: default
|
||||
|
||||
# consider every intermediate target as final to avoid deleting intermediate files
|
||||
.SECONDARY:
|
||||
|
||||
# disable builtin rules that overload the build process (and the debug log !!)
|
||||
.SUFFIXES:
|
||||
MAKEFLAGS += -r
|
||||
|
||||
SHELL = /bin/bash
|
||||
#.ONESHELL:
|
||||
|
||||
|
||||
############
|
||||
# Platform #
|
||||
############
|
||||
PROG := token-daosend
|
||||
|
||||
CONFIG_PRODUCTIONS := bin/$(PROG)
|
||||
|
||||
SOURCE_PATH := src_daosend $(BOLOS_SDK)/src src_usb src_common src_tmp
|
||||
SOURCE_FILES := $(foreach path, $(SOURCE_PATH),$(shell find $(path) | grep "\.c$$") )
|
||||
INCLUDES_PATH := src_usb $(dir $(shell find src_usb/ | grep "\.h$$")) include src_daosend $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm src_common src_tmp
|
||||
|
||||
### platform definitions
|
||||
DEFINES := ST31 gcc __IO=volatile
|
||||
|
||||
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
|
||||
DEFINES += HAVE_BAGL HAVE_PRINTF
|
||||
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64
|
||||
DEFINES += HAVE_BLE
|
||||
|
||||
##############
|
||||
# Compiler #
|
||||
##############
|
||||
GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
||||
CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin
|
||||
CC := $(CLANGPATH)/clang
|
||||
|
||||
CFLAGS :=
|
||||
CFLAGS += -gdwarf-2 -gstrict-dwarf
|
||||
CFLAGS += -O0
|
||||
#CFLAGS += -O0 -g3
|
||||
#CFLAGS += -O3 -Os
|
||||
CFLAGS += -mcpu=cortex-m0 -mthumb
|
||||
CFLAGS += -fno-common -mtune=cortex-m0 -mlittle-endian
|
||||
CFLAGS += -std=gnu99 -Werror=int-to-pointer-cast -Wall -Wextra #-save-temps
|
||||
CFLAGS += -fdata-sections -ffunction-sections -funsigned-char -fshort-enums
|
||||
CFLAGS += -mno-unaligned-access
|
||||
CFLAGS += -Wno-unused-parameter -Wno-duplicate-decl-specifier
|
||||
|
||||
CFLAGS += -fropi --target=armv6m-none-eabi
|
||||
#CFLAGS += -finline-limit-0 -funsigned-bitfields
|
||||
|
||||
AS := $(GCCPATH)/arm-none-eabi-gcc
|
||||
AFLAGS += -ggdb2 -O3 -Os -mcpu=cortex-m0 -fno-common -mtune=cortex-m0
|
||||
|
||||
# NOT SUPPORTED BY STM3L152 CFLAGS += -fpack-struct
|
||||
#-pg --coverage
|
||||
LD := $(GCCPATH)/arm-none-eabi-gcc
|
||||
LDFLAGS :=
|
||||
LDFLAGS += -gdwarf-2 -gstrict-dwarf
|
||||
#LDFLAGS += -O0 -g3
|
||||
LDFLAGS += -O3 -Os
|
||||
#LDFLAGS += -O0
|
||||
LDFLAGS += -Wall
|
||||
LDFLAGS += -mcpu=cortex-m0 -mthumb
|
||||
LDFLAGS += -fno-common -ffunction-sections -fdata-sections -fwhole-program -nostartfiles
|
||||
LDFLAGS += -mno-unaligned-access
|
||||
#LDFLAGS += -nodefaultlibs
|
||||
#LDFLAGS += -nostdlib -nostdinc
|
||||
LDFLAGS += -Tscript.ld -Wl,--gc-sections -Wl,-Map,debug/$(PROG).map,--cref
|
||||
LDLIBS += -Wl,--library-path -Wl,$(GCCPATH)/../lib/armv6-m/
|
||||
#LDLIBS += -Wl,--start-group
|
||||
LDLIBS += -lm -lgcc -lc
|
||||
#LDLIBS += -Wl,--end-group
|
||||
# -mno-unaligned-access
|
||||
#-pg --coverage
|
||||
|
||||
### computed variables
|
||||
VPATH := $(dir $(SOURCE_FILES))
|
||||
OBJECT_FILES := $(sort $(addprefix obj/, $(addsuffix .o, $(basename $(notdir $(SOURCE_FILES))))))
|
||||
DEPEND_FILES := $(sort $(addprefix dep/, $(addsuffix .d, $(basename $(notdir $(SOURCE_FILES))))))
|
||||
|
||||
ifeq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
-include $(DEPEND_FILES)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -fr obj bin debug dep
|
||||
|
||||
prepare:
|
||||
@mkdir -p bin obj debug dep
|
||||
$(info $(SOURCE_FILES))
|
||||
$(info $(DEPEND_FILES))
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
# default is not to display make commands
|
||||
log = $(if $(strip $(VERBOSE)),$1,@$1)
|
||||
|
||||
default: prepare bin/$(PROG)
|
||||
|
||||
load:
|
||||
python -m ledgerblue.loadApp --appFlags 0xc0 --fileName bin/$(PROG).hex --appName $(APPNAME)
|
||||
|
||||
delete:
|
||||
python -m ledgerblue.deleteApp --appName $(APPNAME)
|
||||
|
||||
bin/$(PROG): $(OBJECT_FILES) script.ld
|
||||
@echo "[LINK] $@"
|
||||
$(call log,$(call link_cmdline,$(OBJECT_FILES) $(LDLIBS),$@))
|
||||
$(call log,$(GCCPATH)/arm-none-eabi-objcopy -O ihex -S bin/$(PROG) bin/$(PROG).hex)
|
||||
$(call log,mv bin/$(PROG) bin/$(PROG).elf)
|
||||
$(call log,cp bin/$(PROG).elf obj)
|
||||
$(call log,$(GCCPATH)/arm-none-eabi-objdump -S -d bin/$(PROG).elf > debug/$(PROG).asm)
|
||||
|
||||
dep/%.d: %.c Makefile.daosend
|
||||
@echo "[DEP] $@"
|
||||
@mkdir -p dep
|
||||
$(call log,$(call dep_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
obj/%.o: %.c dep/%.d
|
||||
@echo "[CC] $@"
|
||||
$(call log,$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
obj/%.o: %.s
|
||||
@echo "[CC] $@"
|
||||
$(call log,$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
|
||||
### BEGIN GCC COMPILER RULES
|
||||
|
||||
# link_cmdline(objects,dest) Macro that is used to format arguments for the linker
|
||||
link_cmdline = $(LD) $(LDFLAGS) -o $(2) $(1)
|
||||
|
||||
# dep_cmdline(include,defines,src($<),dest($@)) Macro that is used to format arguments for the dependency creator
|
||||
dep_cmdline = $(CC) -M $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) $(3) | sed 's/\($*\)\.o[ :]*/obj\/\1.o: /g' | sed -e 's/[:\t ][^ ]\+\.c//g' > dep/$(basename $(notdir $(4))).d 2>/dev/null
|
||||
|
||||
# cc_cmdline(include,defines,src,dest) Macro that is used to format arguments for the compiler
|
||||
cc_cmdline = $(CC) -c $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3)
|
||||
|
||||
as_cmdline = $(AS) -c $(AFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3)
|
||||
|
||||
### END GCC COMPILER RULES
|
||||
|
||||
170
Makefile.genericwallet
Executable file
170
Makefile.genericwallet
Executable file
@@ -0,0 +1,170 @@
|
||||
#*******************************************************************************
|
||||
# Ledger Blue
|
||||
# (c) 2016 Ledger
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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.
|
||||
#*******************************************************************************
|
||||
|
||||
APPNAME = ETH
|
||||
|
||||
|
||||
################
|
||||
# Default rule #
|
||||
################
|
||||
|
||||
all: default
|
||||
|
||||
# consider every intermediate target as final to avoid deleting intermediate files
|
||||
.SECONDARY:
|
||||
|
||||
# disable builtin rules that overload the build process (and the debug log !!)
|
||||
.SUFFIXES:
|
||||
MAKEFLAGS += -r
|
||||
|
||||
SHELL = /bin/bash
|
||||
#.ONESHELL:
|
||||
|
||||
|
||||
############
|
||||
# Platform #
|
||||
############
|
||||
PROG := token-genericwallet
|
||||
|
||||
CONFIG_PRODUCTIONS := bin/$(PROG)
|
||||
|
||||
SOURCE_PATH := src_genericwallet $(BOLOS_SDK)/src src_usb src_common src_tmp
|
||||
SOURCE_FILES := $(foreach path, $(SOURCE_PATH),$(shell find $(path) | grep "\.c$$") )
|
||||
INCLUDES_PATH := src_usb $(dir $(shell find src_usb/ | grep "\.h$$")) include src_genericwallet $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm src_common src_tmp
|
||||
|
||||
### platform definitions
|
||||
DEFINES := ST31 gcc __IO=volatile
|
||||
|
||||
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
|
||||
DEFINES += HAVE_BAGL HAVE_PRINTF
|
||||
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64
|
||||
DEFINES += HAVE_BLE
|
||||
|
||||
##############
|
||||
# Compiler #
|
||||
##############
|
||||
GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
||||
CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin
|
||||
CC := $(CLANGPATH)/clang
|
||||
|
||||
CFLAGS :=
|
||||
CFLAGS += -gdwarf-2 -gstrict-dwarf
|
||||
CFLAGS += -O0
|
||||
#CFLAGS += -O0 -g3
|
||||
#CFLAGS += -O3 -Os
|
||||
CFLAGS += -mcpu=cortex-m0 -mthumb
|
||||
CFLAGS += -fno-common -mtune=cortex-m0 -mlittle-endian
|
||||
CFLAGS += -std=gnu99 -Werror=int-to-pointer-cast -Wall -Wextra #-save-temps
|
||||
CFLAGS += -fdata-sections -ffunction-sections -funsigned-char -fshort-enums
|
||||
CFLAGS += -mno-unaligned-access
|
||||
CFLAGS += -Wno-unused-parameter -Wno-duplicate-decl-specifier
|
||||
|
||||
CFLAGS += -fropi --target=armv6m-none-eabi
|
||||
#CFLAGS += -finline-limit-0 -funsigned-bitfields
|
||||
|
||||
AS := $(GCCPATH)/arm-none-eabi-gcc
|
||||
AFLAGS += -ggdb2 -O3 -Os -mcpu=cortex-m0 -fno-common -mtune=cortex-m0
|
||||
|
||||
# NOT SUPPORTED BY STM3L152 CFLAGS += -fpack-struct
|
||||
#-pg --coverage
|
||||
LD := $(GCCPATH)/arm-none-eabi-gcc
|
||||
LDFLAGS :=
|
||||
LDFLAGS += -gdwarf-2 -gstrict-dwarf
|
||||
#LDFLAGS += -O0 -g3
|
||||
LDFLAGS += -O3 -Os
|
||||
#LDFLAGS += -O0
|
||||
LDFLAGS += -Wall
|
||||
LDFLAGS += -mcpu=cortex-m0 -mthumb
|
||||
LDFLAGS += -fno-common -ffunction-sections -fdata-sections -fwhole-program -nostartfiles
|
||||
LDFLAGS += -mno-unaligned-access
|
||||
#LDFLAGS += -nodefaultlibs
|
||||
#LDFLAGS += -nostdlib -nostdinc
|
||||
LDFLAGS += -Tscript.ld -Wl,--gc-sections -Wl,-Map,debug/$(PROG).map,--cref
|
||||
LDLIBS += -Wl,--library-path -Wl,$(GCCPATH)/../lib/armv6-m/
|
||||
#LDLIBS += -Wl,--start-group
|
||||
LDLIBS += -lm -lgcc -lc
|
||||
#LDLIBS += -Wl,--end-group
|
||||
# -mno-unaligned-access
|
||||
#-pg --coverage
|
||||
|
||||
### computed variables
|
||||
VPATH := $(dir $(SOURCE_FILES))
|
||||
OBJECT_FILES := $(sort $(addprefix obj/, $(addsuffix .o, $(basename $(notdir $(SOURCE_FILES))))))
|
||||
DEPEND_FILES := $(sort $(addprefix dep/, $(addsuffix .d, $(basename $(notdir $(SOURCE_FILES))))))
|
||||
|
||||
ifeq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
-include $(DEPEND_FILES)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -fr obj bin debug dep
|
||||
|
||||
prepare:
|
||||
@mkdir -p bin obj debug dep
|
||||
$(info $(SOURCE_FILES))
|
||||
$(info $(DEPEND_FILES))
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
# default is not to display make commands
|
||||
log = $(if $(strip $(VERBOSE)),$1,@$1)
|
||||
|
||||
default: prepare bin/$(PROG)
|
||||
|
||||
load:
|
||||
python -m ledgerblue.loadApp --appFlags 0xc0 --fileName bin/$(PROG).hex --appName $(APPNAME)
|
||||
|
||||
delete:
|
||||
python -m ledgerblue.deleteApp --appName $(APPNAME)
|
||||
|
||||
bin/$(PROG): $(OBJECT_FILES) script.ld
|
||||
@echo "[LINK] $@"
|
||||
$(call log,$(call link_cmdline,$(OBJECT_FILES) $(LDLIBS),$@))
|
||||
$(call log,$(GCCPATH)/arm-none-eabi-objcopy -O ihex -S bin/$(PROG) bin/$(PROG).hex)
|
||||
$(call log,mv bin/$(PROG) bin/$(PROG).elf)
|
||||
$(call log,cp bin/$(PROG).elf obj)
|
||||
$(call log,$(GCCPATH)/arm-none-eabi-objdump -S -d bin/$(PROG).elf > debug/$(PROG).asm)
|
||||
|
||||
dep/%.d: %.c Makefile.genericwallet
|
||||
@echo "[DEP] $@"
|
||||
@mkdir -p dep
|
||||
$(call log,$(call dep_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
obj/%.o: %.c dep/%.d
|
||||
@echo "[CC] $@"
|
||||
$(call log,$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
obj/%.o: %.s
|
||||
@echo "[CC] $@"
|
||||
$(call log,$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@))
|
||||
|
||||
|
||||
### BEGIN GCC COMPILER RULES
|
||||
|
||||
# link_cmdline(objects,dest) Macro that is used to format arguments for the linker
|
||||
link_cmdline = $(LD) $(LDFLAGS) -o $(2) $(1)
|
||||
|
||||
# dep_cmdline(include,defines,src($<),dest($@)) Macro that is used to format arguments for the dependency creator
|
||||
dep_cmdline = $(CC) -M $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) $(3) | sed 's/\($*\)\.o[ :]*/obj\/\1.o: /g' | sed -e 's/[:\t ][^ ]\+\.c//g' > dep/$(basename $(notdir $(4))).d 2>/dev/null
|
||||
|
||||
# cc_cmdline(include,defines,src,dest) Macro that is used to format arguments for the compiler
|
||||
cc_cmdline = $(CC) -c $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3)
|
||||
|
||||
as_cmdline = $(AS) -c $(AFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3)
|
||||
|
||||
### END GCC COMPILER RULES
|
||||
|
||||
11
README.md
11
README.md
@@ -1,2 +1,11 @@
|
||||
# blue-app-eth
|
||||
Ethereum wallet application for Ledger Blue
|
||||
Ethereum wallet application framework for Ledger Blue
|
||||
|
||||
This follows the specification available in the doc/ folder
|
||||
|
||||
To use the generic wallet (disabling all data transaction) refer to signTx.py
|
||||
|
||||
An example application reusing the Ethereum parsing framework to implement some advanced use case (transfering The DAO tokens) is also provided
|
||||
|
||||
For more information refer to the Medium post available shortly
|
||||
|
||||
|
||||
215
doc/ethapp.asc
Normal file
215
doc/ethapp.asc
Normal file
@@ -0,0 +1,215 @@
|
||||
Ethereum application : Common Technical Specifications
|
||||
=======================================================
|
||||
Ledger Firmware Team <hello@ledger.fr>
|
||||
Application version 1.0 - 28th of May 2016
|
||||
|
||||
== 1.0
|
||||
- Initial release
|
||||
|
||||
== About
|
||||
|
||||
This application describes the APDU messages interface to communicate with the Ethereum application.
|
||||
|
||||
The application covers the following functionalities :
|
||||
|
||||
- Retrieve a public Ethereum address given a BIP 32 path
|
||||
- Sign a basic Ethereum transaction given a BIP 32 path
|
||||
- Provide callbacks to validate the data associated to an Ethereum transaction
|
||||
|
||||
The application interface can be accessed over HID or BLE
|
||||
|
||||
== General purpose APDUs
|
||||
|
||||
=== GET ETH PUBLIC ADDRESS
|
||||
|
||||
==== Description
|
||||
|
||||
This command returns the public key and Ethereum address for the given BIP 32 path.
|
||||
|
||||
The address can be optionally checked on the device before being returned.
|
||||
|
||||
==== Coding
|
||||
|
||||
'Command'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le*
|
||||
| E0 | 02 | 00 : return address
|
||||
|
||||
01 : display address and confirm before returning
|
||||
| 00 | variable | variable
|
||||
|==============================================================================================================================
|
||||
|
||||
'Input data'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| Number of BIP 32 derivations to perform (max 10) | 1
|
||||
| First derivation index (big endian) | 4
|
||||
| ... | 4
|
||||
| Last derivation index (big endian) | 4
|
||||
|==============================================================================================================================
|
||||
|
||||
'Output data'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| Public Key length | 1
|
||||
| Uncompressed Public Key | var
|
||||
| Ethereum address length | 1
|
||||
| Ethereum address | var
|
||||
|==============================================================================================================================
|
||||
|
||||
|
||||
=== SIGN ETH TRANSACTION
|
||||
|
||||
==== Description
|
||||
|
||||
This command signs an Ethereum transaction after having the user validate the following parameters
|
||||
|
||||
- Gas price
|
||||
- Gas limit
|
||||
- Recipient address
|
||||
- Value
|
||||
|
||||
The input data is the RLP encoded transaction (as per https://github.com/ethereum/pyethereum/blob/develop/ethereum/transactions.py#L22), without v/r/s present, streamed to the device in 255 bytes maximum data chunks.
|
||||
|
||||
==== Coding
|
||||
|
||||
'Command'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le*
|
||||
| E0 | 04 | 00 : first transaction data block
|
||||
|
||||
80 : subsequent transaction data block
|
||||
| 00 | variable | variable
|
||||
|==============================================================================================================================
|
||||
|
||||
'Input data (first transaction data block)'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| Number of BIP 32 derivations to perform (max 10) | 1
|
||||
| First derivation index (big endian) | 4
|
||||
| ... | 4
|
||||
| Last derivation index (big endian) | 4
|
||||
| RLP transaction chunk | variable
|
||||
|==============================================================================================================================
|
||||
|
||||
'Input data (other transaction data block)'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| RLP transaction chunk | variable
|
||||
|==============================================================================================================================
|
||||
|
||||
|
||||
'Output data'
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| v | 1
|
||||
| r | 32
|
||||
| s | 32
|
||||
|======================================================================================================
|
||||
========================
|
||||
|
||||
== Transport protocol
|
||||
|
||||
=== General transport description
|
||||
|
||||
Ledger APDUs requests and responses are encapsulated using a flexible protocol allowing to fragment large payloads over different underlying transport mechanisms.
|
||||
|
||||
The common transport header is defined as follows :
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| Communication channel ID (big endian) | 2
|
||||
| Command tag | 1
|
||||
| Packet sequence index (big endian) | 2
|
||||
| Payload | var
|
||||
|==============================================================================================================================
|
||||
|
||||
The Communication channel ID allows commands multiplexing over the same physical link. It is not used for the time being, and should be set to 0101 to avoid compatibility issues with implementations ignoring a leading 00 byte.
|
||||
|
||||
The Command tag describes the message content. Use TAG_APDU (0x05) for standard APDU payloads, or TAG_PING (0x02) for a simple link test.
|
||||
|
||||
The Packet sequence index describes the current sequence for fragmented payloads. The first fragment index is 0x00.
|
||||
|
||||
=== APDU Command payload encoding
|
||||
|
||||
APDU Command payloads are encoded as follows :
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| APDU length (big endian) | 2
|
||||
| APDU CLA | 1
|
||||
| APDU INS | 1
|
||||
| APDU P1 | 1
|
||||
| APDU P2 | 1
|
||||
| APDU length | 1
|
||||
| Optional APDU data | var
|
||||
|==============================================================================================================================
|
||||
|
||||
APDU payload is encoded according to the APDU case
|
||||
|
||||
[width="80%"]
|
||||
|=======================================================================================
|
||||
| Case Number | *Lc* | *Le* | Case description
|
||||
| 1 | 0 | 0 | No data in either direction - L is set to 00
|
||||
| 2 | 0 | !0 | Input Data present, no Output Data - L is set to Lc
|
||||
| 3 | !0 | 0 | Output Data present, no Input Data - L is set to Le
|
||||
| 4 | !0 | !0 | Both Input and Output Data are present - L is set to Lc
|
||||
|=======================================================================================
|
||||
|
||||
=== APDU Response payload encoding
|
||||
|
||||
APDU Response payloads are encoded as follows :
|
||||
|
||||
[width="80%"]
|
||||
|==============================================================================================================================
|
||||
| *Description* | *Length*
|
||||
| APDU response length (big endian) | 2
|
||||
| APDU response data and Status Word | var
|
||||
|==============================================================================================================================
|
||||
|
||||
=== USB mapping
|
||||
|
||||
Messages are exchanged with the dongle over HID endpoints over interrupt transfers, with each chunk being 64 bytes long. The HID Report ID is ignored.
|
||||
|
||||
=== BLE mapping
|
||||
|
||||
A similar encoding is used over BLE, without the Communication channel ID.
|
||||
|
||||
The application acts as a GATT server defining service UUID D973F2E0-B19E-11E2-9E96-0800200C9A66
|
||||
|
||||
When using this service, the client sends requests to the characteristic D973F2E2-B19E-11E2-9E96-0800200C9A66, and gets notified on the characteristic D973F2E1-B19E-11E2-9E96-0800200C9A66 after registering for it.
|
||||
|
||||
Requests are encoded using the standard BLE 20 bytes MTU size
|
||||
|
||||
== Status Words
|
||||
|
||||
The following standard Status Words are returned for all APDUs - some specific Status Words can be used for specific commands and are mentioned in the command description.
|
||||
|
||||
'Status Words'
|
||||
|
||||
[width="80%"]
|
||||
|===============================================================================================
|
||||
| *SW* | *Description*
|
||||
| 6700 | Incorrect length
|
||||
| 6982 | Security status not satisfied (Canceled by user)
|
||||
| 6A80 | Invalid data
|
||||
| 6B00 | Incorrect parameter P1 or P2
|
||||
| 6Fxx | Technical problem (Internal error, please report)
|
||||
| 9000 | Normal ending of the command
|
||||
|================================================================================================
|
||||
54
getPublicKey.py
Normal file
54
getPublicKey.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************
|
||||
"""
|
||||
from ledgerblue.comm import getDongle
|
||||
from ledgerblue.commException import CommException
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
def parse_bip32_path(path):
|
||||
if len(path) == 0:
|
||||
return ""
|
||||
result = ""
|
||||
elements = path.split('/')
|
||||
for pathElement in elements:
|
||||
element = pathElement.split('\'')
|
||||
if len(element) == 1:
|
||||
result = result + struct.pack(">I", int(element[0]))
|
||||
else:
|
||||
result = result + struct.pack(">I", 0x80000000 | int(element[0]))
|
||||
return result
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--path', help="BIP 32 path to retrieve")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.path == None:
|
||||
args.path = "44'/60'/0'/0/0"
|
||||
|
||||
donglePath = parse_bip32_path(args.path)
|
||||
apdu = "e0020100".decode('hex') + chr(len(donglePath) + 1) + chr(len(donglePath) / 4) + donglePath
|
||||
|
||||
dongle = getDongle(True)
|
||||
result = dongle.exchange(bytes(apdu))
|
||||
offset = 1 + result[0]
|
||||
address = result[offset + 1 : offset + 1 + result[offset]]
|
||||
|
||||
print "Public key " + str(result[1 : 1 + result[0]]).encode('hex')
|
||||
print "Address 0x" + str(address)
|
||||
159
script.ld
Normal file
159
script.ld
Normal file
@@ -0,0 +1,159 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue - Secure firmware
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
/**
|
||||
* Global chip memory layout and constants
|
||||
*
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
DISCARD (rwx) : ORIGIN = 0xd0000000, LENGTH = 1M
|
||||
|
||||
FLASH (rx) : ORIGIN = 0xc0d00000, LENGTH = 400K
|
||||
SRAM (rwx) : ORIGIN = 0x20001800, LENGTH = 6K
|
||||
}
|
||||
|
||||
PAGE_SIZE = 256;
|
||||
STACK_SIZE = 2048;
|
||||
END_STACK = ORIGIN(SRAM) + LENGTH(SRAM);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
ENTRY(main)
|
||||
|
||||
/****************************************************************/
|
||||
/* This section locates the code in FLASH */
|
||||
/****************************************************************/
|
||||
|
||||
/** put text in Flash memory, VMA will be equal to LMA */
|
||||
.text :
|
||||
{
|
||||
/* provide start code symbol, shall be zero */
|
||||
_text = .;
|
||||
|
||||
PROVIDE(_setjmp = setjmp); /*thanks clang*/
|
||||
|
||||
/* ensure main is always @ 0xC0D00000 */
|
||||
*(.boot*)
|
||||
|
||||
/* place the other code and rodata defined BUT nvram variables that are displaced in a r/w area */
|
||||
*(.text*)
|
||||
*(EXCLUDE_FILE (*_nvram_*) .rodata*) /*.data.rel.ro* not here to detect invalid PIC usage */
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
/* all code placed */
|
||||
_etext = .;
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
|
||||
/* NVM data (ex-filesystem) */
|
||||
*(.bss.N_*)
|
||||
|
||||
} > FLASH = 0x00
|
||||
|
||||
.data (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
||||
/**
|
||||
* Place RAM initialized variables
|
||||
*/
|
||||
_data = .;
|
||||
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
_edata = .;
|
||||
|
||||
} > DISCARD /*> SRAM AT>FLASH = 0x00 */
|
||||
|
||||
.bss :
|
||||
{
|
||||
/**
|
||||
* Place RAM uninitialized variables
|
||||
*/
|
||||
_bss = .;
|
||||
*(EXCLUDE_FILE (*_nvram_*) .bss*)
|
||||
_ebss = .;
|
||||
|
||||
|
||||
/**
|
||||
* Reserve stack size
|
||||
*/
|
||||
_stack = .;
|
||||
. = _stack + STACK_SIZE;
|
||||
PROVIDE( _stack_size = STACK_SIZE );
|
||||
PROVIDE( _estack = ABSOLUTE(END_STACK) );
|
||||
|
||||
} > SRAM = 0x00
|
||||
|
||||
.nvram :
|
||||
{
|
||||
/** Place other configuration */
|
||||
*_nvram_*(.rodata*)
|
||||
} > FLASH = 0x00
|
||||
|
||||
/****************************************************************/
|
||||
/* DEBUG */
|
||||
/****************************************************************/
|
||||
|
||||
/* remove the debugging information from the standard libraries */
|
||||
DISCARD (NOLOAD) :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
|
||||
}
|
||||
49
setSelfAddress.py
Normal file
49
setSelfAddress.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************
|
||||
"""
|
||||
from ledgerblue.comm import getDongle
|
||||
from ledgerblue.commException import CommException
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
def parse_bip32_path(path):
|
||||
if len(path) == 0:
|
||||
return ""
|
||||
result = ""
|
||||
elements = path.split('/')
|
||||
for pathElement in elements:
|
||||
element = pathElement.split('\'')
|
||||
if len(element) == 1:
|
||||
result = result + struct.pack(">I", int(element[0]))
|
||||
else:
|
||||
result = result + struct.pack(">I", 0x80000000 | int(element[0]))
|
||||
return result
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--path', help="BIP 32 path to retrieve")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.path == None:
|
||||
args.path = "44'/60'/0'/0/0"
|
||||
|
||||
donglePath = parse_bip32_path(args.path)
|
||||
apdu = "e0060000".decode('hex') + chr(len(donglePath) + 1) + chr(len(donglePath) / 4) + donglePath
|
||||
|
||||
dongle = getDongle(True)
|
||||
dongle.exchange(bytes(apdu))
|
||||
87
signTx.py
Normal file
87
signTx.py
Normal file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************
|
||||
"""
|
||||
from ledgerblue.comm import getDongle
|
||||
from ledgerblue.commException import CommException
|
||||
import argparse
|
||||
import struct
|
||||
from decimal import Decimal
|
||||
from ethereum.transactions import Transaction, UnsignedTransaction
|
||||
from rlp import encode
|
||||
from rlp.utils import decode_hex, encode_hex, str_to_bytes
|
||||
|
||||
from ethereum import utils
|
||||
|
||||
def parse_bip32_path(path):
|
||||
if len(path) == 0:
|
||||
return ""
|
||||
result = ""
|
||||
elements = path.split('/')
|
||||
for pathElement in elements:
|
||||
element = pathElement.split('\'')
|
||||
if len(element) == 1:
|
||||
result = result + struct.pack(">I", int(element[0]))
|
||||
else:
|
||||
result = result + struct.pack(">I", 0x80000000 | int(element[0]))
|
||||
return result
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--nonce', help="Nonce associated to the account")
|
||||
parser.add_argument('--gasprice', help="Network gas price")
|
||||
parser.add_argument('--startgas', help="startgas", default='21000')
|
||||
parser.add_argument('--amount', help="Amount to send in ether")
|
||||
parser.add_argument('--to', help="Destination address")
|
||||
parser.add_argument('--path', help="BIP 32 path to sign with")
|
||||
parser.add_argument('--data', help="Data to add, hex encoded")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.path == None:
|
||||
args.path = "44'/60'/0'/0/0"
|
||||
|
||||
if args.data == None:
|
||||
args.data = ""
|
||||
else:
|
||||
args.data = decode_hex(args.data[2:])
|
||||
|
||||
amount = Decimal(args.amount) * 10**18
|
||||
|
||||
tx = Transaction(
|
||||
nonce=int(args.nonce),
|
||||
gasprice=int(args.gasprice),
|
||||
startgas=int(args.startgas),
|
||||
to=decode_hex(args.to[2:]),
|
||||
value=int(amount),
|
||||
data=args.data
|
||||
)
|
||||
|
||||
encodedTx = encode(tx, UnsignedTransaction)
|
||||
|
||||
donglePath = parse_bip32_path(args.path)
|
||||
apdu = "e0040000".decode('hex') + chr(len(donglePath) + 1 + len(encodedTx)) + chr(len(donglePath) / 4) + donglePath + encodedTx
|
||||
|
||||
dongle = getDongle(True)
|
||||
result = dongle.exchange(bytes(apdu))
|
||||
|
||||
v = result[0]
|
||||
r = int(str(result[1:1 + 32]).encode('hex'), 16)
|
||||
s = int(str(result[1 + 32: 1 + 32 + 32]).encode('hex'), 16)
|
||||
|
||||
tx = Transaction(tx.nonce, tx.gasprice, tx.startgas, tx.to, tx.value, tx.data, v, r, s)
|
||||
|
||||
print "Signed transaction " + encode_hex(encode(tx))
|
||||
339
src_common/ethUstream.c
Normal file
339
src_common/ethUstream.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "ethUstream.h"
|
||||
#include "ethUtils.h"
|
||||
|
||||
#define MAX_INT256 32
|
||||
#define MAX_ADDRESS 20
|
||||
|
||||
void initTx(txContext_t *context, app_cx_sha3_t *sha3, txContent_t *content,
|
||||
ustreamProcess_t customProcessor, void *extra) {
|
||||
os_memset(context, 0, sizeof(txContext_t));
|
||||
context->sha3 = sha3;
|
||||
context->content = content;
|
||||
context->customProcessor = customProcessor;
|
||||
context->extra = extra;
|
||||
context->currentField = TX_RLP_CONTENT;
|
||||
app_cx_sha3_init(context->sha3, 256);
|
||||
}
|
||||
|
||||
uint8_t readTxByte(txContext_t *context) {
|
||||
uint8_t data;
|
||||
if (context->commandLength < 1) {
|
||||
screen_printf("readTxByte Underflow\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
data = *context->workBuffer;
|
||||
context->workBuffer++;
|
||||
context->commandLength--;
|
||||
if (context->processingField) {
|
||||
context->currentFieldPos++;
|
||||
}
|
||||
if (!(context->processingField && context->fieldSingleByte)) {
|
||||
app_cx_hash((cx_hash_t*)context->sha3, 0, &data, 1, NULL);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void copyTxData(txContext_t *context, uint8_t *out, uint32_t length) {
|
||||
if (context->commandLength < length) {
|
||||
screen_printf("copyTxData Underflow\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (out != NULL) {
|
||||
os_memmove(out, context->workBuffer, length);
|
||||
}
|
||||
if (!(context->processingField && context->fieldSingleByte)) {
|
||||
app_cx_hash((cx_hash_t*)context->sha3, 0, context->workBuffer, length, NULL);
|
||||
}
|
||||
context->workBuffer += length;
|
||||
context->commandLength -= length;
|
||||
if (context->processingField) {
|
||||
context->currentFieldPos += length;
|
||||
}
|
||||
}
|
||||
|
||||
static void processContent(txContext_t *context) {
|
||||
// Keep the full length for sanity checks, move to the next field
|
||||
if (!context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_CONTENT\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
context->dataLength = context->currentFieldLength;
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
|
||||
static void processNonce(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_NONCE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
screen_printf("Invalid length for RLP_NONCE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, NULL, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void processStartGas(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_STARTGAS\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
screen_printf("Invalid length for RLP_STARTGAS %d\n",
|
||||
context->currentFieldLength);
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->startgas.value + context->currentFieldPos,
|
||||
copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->startgas.length = context->currentFieldLength;
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void processGasprice(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_GASPRICE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
screen_printf("Invalid length for RLP_GASPRICE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->gasprice.value + context->currentFieldPos,
|
||||
copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->gasprice.length = context->currentFieldLength;
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void processValue(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_VALUE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
screen_printf("Invalid length for RLP_VALUE\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->value.value + context->currentFieldPos,
|
||||
copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->value.length = context->currentFieldLength;
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void processTo(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_TO\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_ADDRESS) {
|
||||
screen_printf("Invalid length for RLP_TO\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->destination + context->currentFieldPos,
|
||||
copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void processData(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
screen_printf("Invalid type for RLP_DATA\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
screen_printf("Invalid length for RLP_DATA\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, NULL, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
}
|
||||
|
||||
static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
for (;;) {
|
||||
bool processedCustom = false;
|
||||
if (context->currentField == TX_RLP_DONE) {
|
||||
return USTREAM_FINISHED;
|
||||
}
|
||||
if (context->commandLength == 0) {
|
||||
return USTREAM_PROCESSING;
|
||||
}
|
||||
if (!context->processingField) {
|
||||
bool canDecode = false;
|
||||
uint32_t offset;
|
||||
while (context->commandLength != 0) {
|
||||
bool valid;
|
||||
// Feed the RLP buffer until the length can be decoded
|
||||
context->rlpBuffer[context->rlpBufferPos++] =
|
||||
readTxByte(context);
|
||||
if (rlpCanDecode(context->rlpBuffer, context->rlpBufferPos,
|
||||
&valid)) {
|
||||
// Can decode now, if valid
|
||||
if (!valid) {
|
||||
screen_printf("RLP pre-decode error\n");
|
||||
return USTREAM_FAULT;
|
||||
}
|
||||
canDecode = true;
|
||||
break;
|
||||
}
|
||||
// Cannot decode yet
|
||||
// Sanity check
|
||||
if (context->rlpBufferPos == sizeof(context->rlpBuffer)) {
|
||||
screen_printf("RLP pre-decode logic error\n");
|
||||
return USTREAM_FAULT;
|
||||
}
|
||||
}
|
||||
if (!canDecode) {
|
||||
return USTREAM_PROCESSING;
|
||||
}
|
||||
// Ready to process this field
|
||||
if (!rlpDecodeLength(context->rlpBuffer, context->rlpBufferPos,
|
||||
&context->currentFieldLength, &offset,
|
||||
&context->currentFieldIsList)) {
|
||||
screen_printf("RLP decode error\n");
|
||||
return USTREAM_FAULT;
|
||||
}
|
||||
if (offset == 0) {
|
||||
// Hack for single byte, self encoded
|
||||
context->workBuffer--;
|
||||
context->commandLength++;
|
||||
context->fieldSingleByte = true;
|
||||
} else {
|
||||
context->fieldSingleByte = false;
|
||||
}
|
||||
context->currentFieldPos = 0;
|
||||
context->rlpBufferPos = 0;
|
||||
context->processingField = true;
|
||||
}
|
||||
if (context->customProcessor != NULL) {
|
||||
processedCustom = context->customProcessor(context);
|
||||
}
|
||||
if (!processedCustom) {
|
||||
switch (context->currentField) {
|
||||
case TX_RLP_CONTENT:
|
||||
processContent(context);
|
||||
break;
|
||||
case TX_RLP_NONCE:
|
||||
processNonce(context);
|
||||
break;
|
||||
case TX_RLP_GASPRICE:
|
||||
processGasprice(context);
|
||||
break;
|
||||
case TX_RLP_STARTGAS:
|
||||
processStartGas(context);
|
||||
break;
|
||||
case TX_RLP_VALUE:
|
||||
processValue(context);
|
||||
break;
|
||||
case TX_RLP_TO:
|
||||
processTo(context);
|
||||
break;
|
||||
case TX_RLP_DATA:
|
||||
processData(context);
|
||||
break;
|
||||
default:
|
||||
screen_printf("Invalid RLP decoder context\n");
|
||||
return USTREAM_FAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parserStatus_e processTx(txContext_t *context, uint8_t *buffer,
|
||||
uint32_t length) {
|
||||
parserStatus_e result;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
context->workBuffer = buffer;
|
||||
context->commandLength = length;
|
||||
result = processTxInternal(context);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
result = USTREAM_FAULT;
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
return result;
|
||||
}
|
||||
80
src_common/ethUstream.h
Normal file
80
src_common/ethUstream.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include <stdbool.h>
|
||||
#include "app_cx_sha3.h"
|
||||
|
||||
struct txContext_t;
|
||||
|
||||
typedef bool (*ustreamProcess_t)(struct txContext_t *context);
|
||||
|
||||
typedef enum rlpTxField_e {
|
||||
TX_RLP_NONE = 0,
|
||||
TX_RLP_CONTENT,
|
||||
TX_RLP_NONCE,
|
||||
TX_RLP_GASPRICE,
|
||||
TX_RLP_STARTGAS,
|
||||
TX_RLP_TO,
|
||||
TX_RLP_VALUE,
|
||||
TX_RLP_DATA,
|
||||
TX_RLP_DONE
|
||||
} rlpTxField_e;
|
||||
|
||||
typedef enum parserStatus_e {
|
||||
USTREAM_PROCESSING,
|
||||
USTREAM_FINISHED,
|
||||
USTREAM_FAULT
|
||||
} parserStatus_e;
|
||||
|
||||
typedef struct txInt256_t {
|
||||
uint8_t value[32];
|
||||
uint8_t length;
|
||||
} txInt256_t;
|
||||
|
||||
typedef struct txContent_t {
|
||||
txInt256_t gasprice;
|
||||
txInt256_t startgas;
|
||||
txInt256_t value;
|
||||
uint8_t destination[20];
|
||||
} txContent_t;
|
||||
|
||||
typedef struct txContext_t {
|
||||
rlpTxField_e currentField;
|
||||
app_cx_sha3_t *sha3;
|
||||
uint32_t currentFieldLength;
|
||||
uint32_t currentFieldPos;
|
||||
bool currentFieldIsList;
|
||||
bool processingField;
|
||||
bool fieldSingleByte;
|
||||
uint32_t dataLength;
|
||||
uint8_t rlpBuffer[5];
|
||||
uint32_t rlpBufferPos;
|
||||
uint8_t *workBuffer;
|
||||
uint32_t commandLength;
|
||||
ustreamProcess_t customProcessor;
|
||||
txContent_t *content;
|
||||
void *extra;
|
||||
} txContext_t;
|
||||
|
||||
void initTx(txContext_t *context, app_cx_sha3_t *sha3, txContent_t *content,
|
||||
ustreamProcess_t customProcessor, void *extra);
|
||||
parserStatus_e processTx(txContext_t *context, uint8_t *buffer,
|
||||
uint32_t length);
|
||||
void copyTxData(txContext_t *context, uint8_t *out, uint32_t length);
|
||||
uint8_t readTxByte(txContext_t *context);
|
||||
269
src_common/ethUtils.c
Normal file
269
src_common/ethUtils.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Utilities for an Ethereum Hardware Wallet logic
|
||||
* @file ethUtils.h
|
||||
* @author Ledger Firmware Team <hello@ledger.fr>
|
||||
* @version 1.0
|
||||
* @date 8th of March 2016
|
||||
*/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include <stdbool.h>
|
||||
#include "ethUtils.h"
|
||||
|
||||
bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) {
|
||||
if (*buffer <= 0x7f) {
|
||||
} else if (*buffer <= 0xb7) {
|
||||
} else if (*buffer <= 0xbf) {
|
||||
if (bufferLength < (1 + (*buffer - 0xb7))) {
|
||||
return false;
|
||||
}
|
||||
if (*buffer > 0xbb) {
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
return true;
|
||||
}
|
||||
} else if (*buffer <= 0xf7) {
|
||||
} else {
|
||||
if (bufferLength < (1 + (*buffer - 0xf7))) {
|
||||
return false;
|
||||
}
|
||||
if (*buffer > 0xfb) {
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
uint32_t *fieldLength, uint32_t *offset, bool *list) {
|
||||
if (*buffer <= 0x7f) {
|
||||
*offset = 0;
|
||||
*fieldLength = 1;
|
||||
*list = false;
|
||||
} else if (*buffer <= 0xb7) {
|
||||
*offset = 1;
|
||||
*fieldLength = *buffer - 0x80;
|
||||
*list = false;
|
||||
} else if (*buffer <= 0xbf) {
|
||||
*offset = 1 + (*buffer - 0xb7);
|
||||
*list = false;
|
||||
switch (*buffer) {
|
||||
case 0xb8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xb9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xba:
|
||||
*fieldLength =
|
||||
(*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xbb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
}
|
||||
} else if (*buffer <= 0xf7) {
|
||||
*offset = 1;
|
||||
*fieldLength = *buffer - 0xc0;
|
||||
*list = true;
|
||||
} else {
|
||||
*offset = 1 + (*buffer - 0xf7);
|
||||
*list = true;
|
||||
switch (*buffer) {
|
||||
case 0xf8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xf9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xfa:
|
||||
*fieldLength =
|
||||
(*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xfb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context) {
|
||||
uint8_t hashAddress[32];
|
||||
app_cx_sha3_init(sha3Context, 256);
|
||||
app_cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress);
|
||||
os_memmove(out, hashAddress + 12, 20);
|
||||
}
|
||||
|
||||
static const uint8_t const HEXDIGITS[] = "0123456789abcdef";
|
||||
|
||||
#ifdef CHECKSUM_1
|
||||
|
||||
static const uint8_t const MASK[] = {0x80, 0x40, 0x20, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
char convertDigit(uint8_t *address, uint8_t index, uint8_t *hash) {
|
||||
unsigned char digit = address[index / 2];
|
||||
if ((index % 2) == 0) {
|
||||
digit = (digit >> 4) & 0x0f;
|
||||
} else {
|
||||
digit = digit & 0x0f;
|
||||
}
|
||||
if (digit < 10) {
|
||||
return HEXDIGITS[digit];
|
||||
} else {
|
||||
unsigned char data = hash[index / 8];
|
||||
if (((data & MASK[index % 8]) != 0) && (digit > 9)) {
|
||||
return HEXDIGITS[digit] - 'a' + 'A';
|
||||
} else {
|
||||
return HEXDIGITS[digit];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context) {
|
||||
uint8_t hashAddress[32];
|
||||
app_cx_sha3_init(sha3Context, 256);
|
||||
app_cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context);
|
||||
}
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context) {
|
||||
uint8_t hashChecksum[32];
|
||||
uint8_t i;
|
||||
app_cx_sha3_init(sha3Context, 256);
|
||||
app_cx_hash((cx_hash_t*)sha3Context, CX_LAST, address, 20, hashChecksum);
|
||||
for (i = 0; i < 40; i++) {
|
||||
out[i] = convertDigit(address, i, hashChecksum);
|
||||
}
|
||||
out[40] = '\0';
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context) {
|
||||
uint8_t hashAddress[32];
|
||||
app_cx_sha3_init(sha3Context, 256);
|
||||
app_cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context);
|
||||
}
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context) {
|
||||
uint8_t hashChecksum[32];
|
||||
uint8_t tmp[40];
|
||||
uint8_t i;
|
||||
for (i = 0; i < 20; i++) {
|
||||
uint8_t digit = address[i];
|
||||
tmp[2 * i] = HEXDIGITS[(digit >> 4) & 0x0f];
|
||||
tmp[2 * i + 1] = HEXDIGITS[digit & 0x0f];
|
||||
}
|
||||
app_cx_sha3_init(sha3Context, 256);
|
||||
app_cx_hash((cx_hash_t*)sha3Context, CX_LAST, tmp, 40, hashChecksum);
|
||||
for (i = 0; i < 40; i++) {
|
||||
uint8_t hashDigit = hashChecksum[i / 2];
|
||||
if ((i % 2) == 0) {
|
||||
hashDigit = (hashDigit >> 4) & 0x0f;
|
||||
} else {
|
||||
hashDigit = hashDigit & 0x0f;
|
||||
}
|
||||
if ((hashDigit > 7) && (tmp[i] > '9')) {
|
||||
out[i] = tmp[i] - 'a' + 'A';
|
||||
} else {
|
||||
out[i] = tmp[i];
|
||||
}
|
||||
}
|
||||
out[40] = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
uint32_t targetLength, uint8_t decimals) {
|
||||
uint32_t startOffset;
|
||||
uint32_t lastZeroOffset = 0;
|
||||
uint32_t offset = 0;
|
||||
if (srcLength == decimals) {
|
||||
if (targetLength < srcLength + 1) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < srcLength; i++) {
|
||||
target[i] = src[i];
|
||||
}
|
||||
target[srcLength] = '\0';
|
||||
return true;
|
||||
}
|
||||
if (srcLength < decimals) {
|
||||
uint32_t delta = decimals - srcLength;
|
||||
if (targetLength < srcLength + 1 + 2 + delta) {
|
||||
return false;
|
||||
}
|
||||
target[offset++] = '0';
|
||||
target[offset++] = '.';
|
||||
for (uint32_t i = 0; i < delta; i++) {
|
||||
target[offset++] = '0';
|
||||
}
|
||||
startOffset = offset;
|
||||
for (uint32_t i = 0; i < srcLength; i++) {
|
||||
target[offset++] = src[i];
|
||||
}
|
||||
target[offset] = '\0';
|
||||
} else {
|
||||
uint32_t sourceOffset = 0;
|
||||
uint32_t delta = srcLength - decimals;
|
||||
if (targetLength < srcLength + 1 + 1) {
|
||||
return false;
|
||||
}
|
||||
while (offset < delta) {
|
||||
target[offset++] = src[sourceOffset++];
|
||||
}
|
||||
target[offset++] = '.';
|
||||
startOffset = offset;
|
||||
while (sourceOffset < srcLength) {
|
||||
target[offset++] = src[sourceOffset++];
|
||||
}
|
||||
}
|
||||
for (uint32_t i = startOffset; i < offset; i++) {
|
||||
if (target[i] == '0') {
|
||||
if (lastZeroOffset == 0) {
|
||||
lastZeroOffset = i;
|
||||
}
|
||||
} else {
|
||||
lastZeroOffset = 0;
|
||||
}
|
||||
}
|
||||
if (lastZeroOffset != 0) {
|
||||
target[lastZeroOffset] = '\0';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
49
src_common/ethUtils.h
Normal file
49
src_common/ethUtils.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include "app_cx_sha3.h"
|
||||
|
||||
/**
|
||||
* @brief Decode an RLP encoded field - see
|
||||
* https://github.com/ethereum/wiki/wiki/RLP
|
||||
* @param [in] buffer buffer containing the RLP encoded field to decode
|
||||
* @param [in] bufferLength size of the buffer
|
||||
* @param [out] fieldLength length of the RLP encoded field
|
||||
* @param [out] offset offset to the beginning of the RLP encoded field from the
|
||||
* buffer
|
||||
* @param [out] list true if the field encodes a list, false if it encodes a
|
||||
* string
|
||||
* @return true if the RLP header is consistent
|
||||
*/
|
||||
bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
uint32_t *fieldLength, uint32_t *offset, bool *list);
|
||||
|
||||
bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid);
|
||||
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context);
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context);
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
app_cx_sha3_t *sha3Context);
|
||||
|
||||
bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
uint32_t targetLength, uint8_t decimals);
|
||||
409
src_common/uint256.c
Normal file
409
src_common/uint256.c
Normal file
@@ -0,0 +1,409 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
// Adapted from https://github.com/calccrypto/uint256_t
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "uint256.h"
|
||||
|
||||
static const char HEXDIGITS[] = "0123456789abcdef";
|
||||
|
||||
static uint64_t readUint64BE(uint8_t *buffer) {
|
||||
return (((uint64_t)buffer[0]) << 56) | (((uint64_t)buffer[1]) << 48) |
|
||||
(((uint64_t)buffer[2]) << 40) | (((uint64_t)buffer[3]) << 32) |
|
||||
(((uint64_t)buffer[4]) << 24) | (((uint64_t)buffer[5]) << 16) |
|
||||
(((uint64_t)buffer[6]) << 8) | (((uint64_t)buffer[7]));
|
||||
}
|
||||
|
||||
void readu128BE(uint8_t *buffer, uint128_t *target) {
|
||||
UPPER_P(target) = readUint64BE(buffer);
|
||||
LOWER_P(target) = readUint64BE(buffer + 8);
|
||||
}
|
||||
|
||||
void readu256BE(uint8_t *buffer, uint256_t *target) {
|
||||
readu128BE(buffer, &UPPER_P(target));
|
||||
readu128BE(buffer + 16, &LOWER_P(target));
|
||||
}
|
||||
|
||||
bool zero128(uint128_t *number) {
|
||||
return ((LOWER_P(number) == 0) && (UPPER_P(number) == 0));
|
||||
}
|
||||
|
||||
bool zero256(uint256_t *number) {
|
||||
return (zero128(&LOWER_P(number)) && zero128(&UPPER_P(number)));
|
||||
}
|
||||
|
||||
void copy128(uint128_t *target, uint128_t *number) {
|
||||
UPPER_P(target) = UPPER_P(number);
|
||||
LOWER_P(target) = LOWER_P(number);
|
||||
}
|
||||
|
||||
void copy256(uint256_t *target, uint256_t *number) {
|
||||
copy128(&UPPER_P(target), &UPPER_P(number));
|
||||
copy128(&LOWER_P(target), &LOWER_P(number));
|
||||
}
|
||||
|
||||
void clear128(uint128_t *target) {
|
||||
UPPER_P(target) = 0;
|
||||
LOWER_P(target) = 0;
|
||||
}
|
||||
|
||||
void clear256(uint256_t *target) {
|
||||
clear128(&UPPER_P(target));
|
||||
clear128(&LOWER_P(target));
|
||||
}
|
||||
|
||||
void shiftl128(uint128_t *number, uint32_t value, uint128_t *target) {
|
||||
if (value >= 128) {
|
||||
clear128(target);
|
||||
} else if (value == 64) {
|
||||
UPPER_P(target) = LOWER_P(number);
|
||||
LOWER_P(target) = 0;
|
||||
} else if (value == 0) {
|
||||
copy128(target, number);
|
||||
} else if (value < 64) {
|
||||
UPPER_P(target) =
|
||||
(UPPER_P(number) << value) + (LOWER_P(number) >> (64 - value));
|
||||
LOWER_P(target) = (LOWER_P(number) << value);
|
||||
} else if ((128 > value) && (value > 64)) {
|
||||
UPPER_P(target) = LOWER_P(number) << (value - 64);
|
||||
LOWER_P(target) = 0;
|
||||
} else {
|
||||
clear128(target);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftl256(uint256_t *number, uint32_t value, uint256_t *target) {
|
||||
if (value >= 256) {
|
||||
clear256(target);
|
||||
} else if (value == 128) {
|
||||
copy128(&UPPER_P(target), &LOWER_P(number));
|
||||
clear128(&LOWER_P(target));
|
||||
} else if (value == 0) {
|
||||
copy256(target, number);
|
||||
} else if (value < 128) {
|
||||
uint128_t tmp1;
|
||||
uint128_t tmp2;
|
||||
uint256_t result;
|
||||
shiftl128(&UPPER_P(number), value, &tmp1);
|
||||
shiftr128(&LOWER_P(number), (128 - value), &tmp2);
|
||||
add128(&tmp1, &tmp2, &UPPER(result));
|
||||
shiftl128(&LOWER_P(number), value, &LOWER(result));
|
||||
copy256(target, &result);
|
||||
} else if ((256 > value) && (value > 128)) {
|
||||
shiftl128(&LOWER_P(number), (value - 128), &UPPER_P(target));
|
||||
clear128(&LOWER_P(target));
|
||||
} else {
|
||||
clear256(target);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftr128(uint128_t *number, uint32_t value, uint128_t *target) {
|
||||
if (value >= 128) {
|
||||
clear128(target);
|
||||
} else if (value == 64) {
|
||||
UPPER_P(target) = 0;
|
||||
LOWER_P(target) = UPPER_P(number);
|
||||
} else if (value == 0) {
|
||||
copy128(target, number);
|
||||
} else if (value < 64) {
|
||||
uint128_t result;
|
||||
UPPER(result) = UPPER_P(number) >> value;
|
||||
LOWER(result) =
|
||||
(UPPER_P(number) << (64 - value)) + (LOWER_P(number) >> value);
|
||||
copy128(target, &result);
|
||||
} else if ((128 > value) && (value > 64)) {
|
||||
LOWER_P(target) = UPPER_P(number) >> (value - 64);
|
||||
UPPER_P(target) = 0;
|
||||
} else {
|
||||
clear128(target);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftr256(uint256_t *number, uint32_t value, uint256_t *target) {
|
||||
if (value >= 256) {
|
||||
clear256(target);
|
||||
} else if (value == 128) {
|
||||
copy128(&LOWER_P(target), &UPPER_P(number));
|
||||
clear128(&UPPER_P(target));
|
||||
} else if (value == 0) {
|
||||
copy256(target, number);
|
||||
} else if (value < 128) {
|
||||
uint128_t tmp1;
|
||||
uint128_t tmp2;
|
||||
uint256_t result;
|
||||
shiftr128(&UPPER_P(number), value, &UPPER(result));
|
||||
shiftr128(&LOWER_P(number), value, &tmp1);
|
||||
shiftl128(&UPPER_P(number), (128 - value), &tmp2);
|
||||
add128(&tmp1, &tmp2, &LOWER(result));
|
||||
copy256(target, &result);
|
||||
} else if ((256 > value) && (value > 128)) {
|
||||
shiftr128(&UPPER_P(number), (value - 128), &LOWER_P(target));
|
||||
clear128(&UPPER_P(target));
|
||||
} else {
|
||||
clear256(target);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bits128(uint128_t *number) {
|
||||
uint32_t result = 0;
|
||||
if (UPPER_P(number)) {
|
||||
result = 64;
|
||||
uint64_t up = UPPER_P(number);
|
||||
while (up) {
|
||||
up >>= 1;
|
||||
result++;
|
||||
}
|
||||
} else {
|
||||
uint64_t low = LOWER_P(number);
|
||||
while (low) {
|
||||
low >>= 1;
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t bits256(uint256_t *number) {
|
||||
uint32_t result = 0;
|
||||
if (!zero128(&UPPER_P(number))) {
|
||||
result = 128;
|
||||
uint128_t up;
|
||||
copy128(&up, &UPPER_P(number));
|
||||
while (!zero128(&up)) {
|
||||
shiftr128(&up, 1, &up);
|
||||
result++;
|
||||
}
|
||||
} else {
|
||||
uint128_t low;
|
||||
copy128(&low, &LOWER_P(number));
|
||||
while (!zero128(&low)) {
|
||||
shiftr128(&low, 1, &low);
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool equal128(uint128_t *number1, uint128_t *number2) {
|
||||
return (UPPER_P(number1) == UPPER_P(number2)) &&
|
||||
(LOWER_P(number1) == LOWER_P(number2));
|
||||
}
|
||||
|
||||
bool equal256(uint256_t *number1, uint256_t *number2) {
|
||||
return (equal128(&UPPER_P(number1), &UPPER_P(number2)) &&
|
||||
equal128(&LOWER_P(number1), &LOWER_P(number2)));
|
||||
}
|
||||
|
||||
bool gt128(uint128_t *number1, uint128_t *number2) {
|
||||
if (UPPER_P(number1) == UPPER_P(number2)) {
|
||||
return (LOWER_P(number1) > LOWER_P(number2));
|
||||
}
|
||||
return (UPPER_P(number1) > UPPER_P(number2));
|
||||
}
|
||||
|
||||
bool gt256(uint256_t *number1, uint256_t *number2) {
|
||||
if (equal128(&UPPER_P(number1), &UPPER_P(number2))) {
|
||||
return gt128(&LOWER_P(number1), &LOWER_P(number2));
|
||||
}
|
||||
return gt128(&UPPER_P(number1), &UPPER_P(number2));
|
||||
}
|
||||
|
||||
bool gte128(uint128_t *number1, uint128_t *number2) {
|
||||
return gt128(number1, number2) || equal128(number1, number2);
|
||||
}
|
||||
|
||||
bool gte256(uint256_t *number1, uint256_t *number2) {
|
||||
return gt256(number1, number2) || equal256(number1, number2);
|
||||
}
|
||||
|
||||
void add128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
UPPER_P(target) =
|
||||
UPPER_P(number1) + UPPER_P(number2) +
|
||||
((LOWER_P(number1) + LOWER_P(number2)) < LOWER_P(number1));
|
||||
LOWER_P(target) = LOWER_P(number1) + LOWER_P(number2);
|
||||
}
|
||||
|
||||
void add256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
uint128_t tmp;
|
||||
add128(&UPPER_P(number1), &UPPER_P(number2), &UPPER_P(target));
|
||||
add128(&LOWER_P(number1), &LOWER_P(number2), &tmp);
|
||||
if (gt128(&LOWER_P(number1), &tmp)) {
|
||||
uint128_t one;
|
||||
UPPER(one) = 0;
|
||||
LOWER(one) = 1;
|
||||
add128(&UPPER_P(target), &one, &UPPER_P(target));
|
||||
}
|
||||
add128(&LOWER_P(number1), &LOWER_P(number2), &LOWER_P(target));
|
||||
}
|
||||
|
||||
void minus128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
UPPER_P(target) =
|
||||
UPPER_P(number1) - UPPER_P(number2) -
|
||||
((LOWER_P(number1) - LOWER_P(number2)) > LOWER_P(number1));
|
||||
LOWER_P(target) = LOWER_P(number1) - LOWER_P(number2);
|
||||
}
|
||||
|
||||
void minus256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
uint128_t tmp;
|
||||
minus128(&UPPER_P(number1), &UPPER_P(number2), &UPPER_P(target));
|
||||
minus128(&LOWER_P(number1), &LOWER_P(number2), &tmp);
|
||||
if (gt128(&tmp, &LOWER_P(number1))) {
|
||||
uint128_t one;
|
||||
UPPER(one) = 0;
|
||||
LOWER(one) = 1;
|
||||
minus128(&UPPER_P(target), &one, &UPPER_P(target));
|
||||
}
|
||||
minus128(&LOWER_P(number1), &LOWER_P(number2), &LOWER_P(target));
|
||||
}
|
||||
|
||||
void or128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
UPPER_P(target) = UPPER_P(number1) | UPPER_P(number2);
|
||||
LOWER_P(target) = LOWER_P(number1) | LOWER_P(number2);
|
||||
}
|
||||
|
||||
void or256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
or128(&UPPER_P(number1), &UPPER_P(number2), &UPPER_P(target));
|
||||
or128(&LOWER_P(number1), &LOWER_P(number2), &LOWER_P(target));
|
||||
}
|
||||
|
||||
void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv,
|
||||
uint128_t *retMod) {
|
||||
uint128_t copyd, adder, resDiv, resMod;
|
||||
uint128_t one;
|
||||
UPPER(one) = 0;
|
||||
LOWER(one) = 1;
|
||||
uint32_t diffBits = bits128(l) - bits128(r);
|
||||
clear128(&resDiv);
|
||||
copy128(&resMod, l);
|
||||
if (gt128(r, l)) {
|
||||
copy128(retMod, l);
|
||||
clear128(retDiv);
|
||||
} else {
|
||||
shiftl128(r, diffBits, ©d);
|
||||
shiftl128(&one, diffBits, &adder);
|
||||
if (gt128(©d, &resMod)) {
|
||||
shiftr128(©d, 1, ©d);
|
||||
shiftr128(&adder, 1, &adder);
|
||||
}
|
||||
while (gte128(&resMod, r)) {
|
||||
if (gte128(&resMod, ©d)) {
|
||||
minus128(&resMod, ©d, &resMod);
|
||||
or128(&resDiv, &adder, &resDiv);
|
||||
}
|
||||
shiftr128(©d, 1, ©d);
|
||||
shiftr128(&adder, 1, &adder);
|
||||
}
|
||||
copy128(retDiv, &resDiv);
|
||||
copy128(retMod, &resMod);
|
||||
}
|
||||
}
|
||||
|
||||
void divmod256(uint256_t *l, uint256_t *r, uint256_t *retDiv,
|
||||
uint256_t *retMod) {
|
||||
uint256_t copyd, adder, resDiv, resMod;
|
||||
uint256_t one;
|
||||
clear256(&one);
|
||||
UPPER(LOWER(one)) = 0;
|
||||
LOWER(LOWER(one)) = 1;
|
||||
uint32_t diffBits = bits256(l) - bits256(r);
|
||||
clear256(&resDiv);
|
||||
copy256(&resMod, l);
|
||||
if (gt256(r, l)) {
|
||||
copy256(retMod, l);
|
||||
clear256(retDiv);
|
||||
} else {
|
||||
shiftl256(r, diffBits, ©d);
|
||||
shiftl256(&one, diffBits, &adder);
|
||||
if (gt256(©d, &resMod)) {
|
||||
shiftr256(©d, 1, ©d);
|
||||
shiftr256(&adder, 1, &adder);
|
||||
}
|
||||
while (gte256(&resMod, r)) {
|
||||
if (gte256(&resMod, ©d)) {
|
||||
minus256(&resMod, ©d, &resMod);
|
||||
or256(&resDiv, &adder, &resDiv);
|
||||
}
|
||||
shiftr256(©d, 1, ©d);
|
||||
shiftr256(&adder, 1, &adder);
|
||||
}
|
||||
copy256(retDiv, &resDiv);
|
||||
copy256(retMod, &resMod);
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseString(char *str, uint32_t length) {
|
||||
uint32_t i, j;
|
||||
for (i = 0, j = length - 1; i < j; i++, j--) {
|
||||
uint8_t c;
|
||||
c = str[i];
|
||||
str[i] = str[j];
|
||||
str[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
bool tostring128(uint128_t *number, uint32_t baseParam, char *out,
|
||||
uint32_t outLength) {
|
||||
uint128_t rDiv;
|
||||
uint128_t rMod;
|
||||
uint128_t base;
|
||||
copy128(&rDiv, number);
|
||||
clear128(&rMod);
|
||||
clear128(&base);
|
||||
LOWER(base) = baseParam;
|
||||
uint32_t offset = 0;
|
||||
if ((baseParam < 2) || (baseParam > 16)) {
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
if (offset > (outLength - 1)) {
|
||||
return false;
|
||||
}
|
||||
divmod128(&rDiv, &base, &rDiv, &rMod);
|
||||
out[offset++] = HEXDIGITS[(uint8_t)LOWER(rMod)];
|
||||
} while (!zero128(&rDiv));
|
||||
out[offset] = '\0';
|
||||
reverseString(out, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tostring256(uint256_t *number, uint32_t baseParam, char *out,
|
||||
uint32_t outLength) {
|
||||
uint256_t rDiv;
|
||||
uint256_t rMod;
|
||||
uint256_t base;
|
||||
copy256(&rDiv, number);
|
||||
clear256(&rMod);
|
||||
clear256(&base);
|
||||
UPPER(LOWER(base)) = 0;
|
||||
LOWER(LOWER(base)) = baseParam;
|
||||
uint32_t offset = 0;
|
||||
if ((baseParam < 2) || (baseParam > 16)) {
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
if (offset > (outLength - 1)) {
|
||||
return false;
|
||||
}
|
||||
divmod256(&rDiv, &base, &rDiv, &rMod);
|
||||
out[offset++] = HEXDIGITS[(uint8_t)LOWER(LOWER(rMod))];
|
||||
} while (!zero256(&rDiv));
|
||||
out[offset] = '\0';
|
||||
reverseString(out, offset);
|
||||
return true;
|
||||
}
|
||||
63
src_common/uint256.h
Normal file
63
src_common/uint256.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
// Adapted from https://github.com/calccrypto/uint256_t
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct uint128_t { uint64_t elements[2]; } uint128_t;
|
||||
|
||||
typedef struct uint256_t { uint128_t elements[2]; } uint256_t;
|
||||
|
||||
#define UPPER_P(x) x->elements[0]
|
||||
#define LOWER_P(x) x->elements[1]
|
||||
#define UPPER(x) x.elements[0]
|
||||
#define LOWER(x) x.elements[1]
|
||||
|
||||
void readu128BE(uint8_t *buffer, uint128_t *target);
|
||||
void readu256BE(uint8_t *buffer, uint256_t *target);
|
||||
bool zero128(uint128_t *number);
|
||||
bool zero256(uint256_t *number);
|
||||
void copy128(uint128_t *target, uint128_t *number);
|
||||
void copy256(uint256_t *target, uint256_t *number);
|
||||
void clear128(uint128_t *target);
|
||||
void clear256(uint256_t *target);
|
||||
void shiftl128(uint128_t *number, uint32_t value, uint128_t *target);
|
||||
void shiftr128(uint128_t *number, uint32_t value, uint128_t *target);
|
||||
void shiftl256(uint256_t *number, uint32_t value, uint256_t *target);
|
||||
void shiftr256(uint256_t *number, uint32_t value, uint256_t *target);
|
||||
uint32_t bits128(uint128_t *number);
|
||||
uint32_t bits256(uint256_t *number);
|
||||
bool equal128(uint128_t *number1, uint128_t *number2);
|
||||
bool equal256(uint256_t *number1, uint256_t *number2);
|
||||
bool gt128(uint128_t *number1, uint128_t *number2);
|
||||
bool gt256(uint256_t *number1, uint256_t *number2);
|
||||
bool gte128(uint128_t *number1, uint128_t *number2);
|
||||
bool gte256(uint256_t *number1, uint256_t *number2);
|
||||
void add128(uint128_t *number1, uint128_t *number2, uint128_t *target);
|
||||
void add256(uint256_t *number1, uint256_t *number2, uint256_t *target);
|
||||
void minus128(uint128_t *number1, uint128_t *number2, uint128_t *target);
|
||||
void minus256(uint256_t *number1, uint256_t *number2, uint256_t *target);
|
||||
void or128(uint128_t *number1, uint128_t *number2, uint128_t *target);
|
||||
void or256(uint256_t *number1, uint256_t *number2, uint256_t *target);
|
||||
void divmod128(uint128_t *l, uint128_t *r, uint128_t *div, uint128_t *mod);
|
||||
void divmod256(uint256_t *l, uint256_t *r, uint256_t *div, uint256_t *mod);
|
||||
bool tostring128(uint128_t *number, uint32_t base, char *out,
|
||||
uint32_t outLength);
|
||||
bool tostring256(uint256_t *number, uint32_t base, char *out,
|
||||
uint32_t outLength);
|
||||
969
src_daosend/main.c
Normal file
969
src_daosend/main.c
Normal file
@@ -0,0 +1,969 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include <stdbool.h>
|
||||
#include "app_cx_sha3.h"
|
||||
#include "ethUstream.h"
|
||||
#include "ethUtils.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include "os_io_seproxyhal.h"
|
||||
#include "string.h"
|
||||
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
|
||||
|
||||
unsigned char usb_enable_request; // request to turn on USB
|
||||
unsigned char uiDone; // notification to come back to the APDU event loop
|
||||
unsigned int
|
||||
currentUiElement; // currently displayed UI element in a set of elements
|
||||
unsigned char
|
||||
element_displayed; // notification of something displayed in a touch handler
|
||||
|
||||
// UI currently displayed
|
||||
enum UI_STATE { UI_IDLE, UI_ADDRESS, UI_APPROVAL };
|
||||
|
||||
enum UI_STATE uiState;
|
||||
|
||||
void io_usb_enable(unsigned char enabled);
|
||||
void os_boot(void);
|
||||
|
||||
unsigned int io_seproxyhal_touch_exit(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_tx_ok(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_address_ok(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_address_cancel(bagl_element_t *e);
|
||||
|
||||
uint32_t set_result_get_publicKey(void);
|
||||
|
||||
#define MAX_BIP32_PATH 10
|
||||
|
||||
#define CLA 0xE0
|
||||
#define INS_GET_PUBLIC_KEY 0x02
|
||||
#define INS_SIGN 0x04
|
||||
#define INS_ADD_SELF 0x06
|
||||
#define P1_CONFIRM 0x01
|
||||
#define P1_NON_CONFIRM 0x00
|
||||
#define P1_FIRST 0x00
|
||||
#define P1_MORE 0x80
|
||||
|
||||
#define OFFSET_CLA 0
|
||||
#define OFFSET_INS 1
|
||||
#define OFFSET_P1 2
|
||||
#define OFFSET_P2 3
|
||||
#define OFFSET_LC 4
|
||||
#define OFFSET_CDATA 5
|
||||
|
||||
#define DAO_TOKENS_UNIT 16
|
||||
|
||||
typedef struct publicKeyContext_t {
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
uint8_t address[41];
|
||||
} publicKeyContext_t;
|
||||
|
||||
typedef struct transactionContext_t {
|
||||
uint8_t pathLength;
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint8_t hash[32];
|
||||
} transactionContext_t;
|
||||
|
||||
typedef struct daosendContext_t {
|
||||
uint8_t data[4 + 32 + 32];
|
||||
uint32_t dataFieldPos;
|
||||
uint8_t selfAddress[20];
|
||||
bool selfAddressProvided;
|
||||
} daosendContext_t;
|
||||
|
||||
char lineBuffer[50];
|
||||
union {
|
||||
publicKeyContext_t publicKeyContext;
|
||||
transactionContext_t transactionContext;
|
||||
} tmpCtx;
|
||||
txContext_t txContext;
|
||||
txContent_t txContent;
|
||||
daosendContext_t daoContext;
|
||||
app_cx_sha3_t sha3;
|
||||
volatile char addressSummary[21];
|
||||
volatile char address1[21];
|
||||
volatile char address2[21];
|
||||
volatile char fullAmount[50];
|
||||
|
||||
static const uint8_t const DAO_TRANSFER_ID[] = {0xa9, 0x05, 0x9c, 0xbb};
|
||||
static const uint8_t const DAO_ADDRESS[] = {
|
||||
0xbb, 0x9b, 0xc2, 0x44, 0xd7, 0x98, 0x12, 0x3f, 0xde, 0x78,
|
||||
0x3f, 0xcc, 0x1c, 0x72, 0xd3, 0xbb, 0x8c, 0x18, 0x94, 0x13};
|
||||
|
||||
// blank the screen
|
||||
static const bagl_element_t const bagl_ui_erase_all[] = {
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 60, 320, 420, 0, 0, BAGL_FILL, 0xf9f9f9,
|
||||
0xf9f9f9, 0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
};
|
||||
|
||||
bagl_element_t const bagl_ui_address[] = {
|
||||
// type id x y w h s r fill
|
||||
// fg bg font icon text, out, over, touch
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"TheDAO send token",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 35, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0xcccccc, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CANCEL",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_address_cancel,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 165, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CONFIRM",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_address_ok,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 0, 147, 320, 32, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
"Confirm address",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 280, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)addressSummary,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 310, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 330, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
};
|
||||
|
||||
// UI to approve or deny the signature proposal
|
||||
static const bagl_element_t const bagl_ui_approval[] = {
|
||||
|
||||
// type id x y w h s r fill
|
||||
// fg bg font icon text, out, over, touch
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"TheDAO send token",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 35, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0xcccccc, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CANCEL",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_tx_cancel,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 165, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CONFIRM",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_tx_ok,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 0, 87, 320, 32, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
"CONFIRM THEDAO TOKENS SEND",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 125, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)fullAmount,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 175, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)addressSummary,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 205, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 225, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
};
|
||||
|
||||
// UI displayed when no signature proposal has been received
|
||||
static const bagl_element_t const bagl_ui_idle[] = {
|
||||
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"TheDAO send token",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 190, 215, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"Exit",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_exit,
|
||||
NULL,
|
||||
NULL}
|
||||
|
||||
};
|
||||
|
||||
unsigned int io_seproxyhal_touch_exit(bagl_element_t *e) {
|
||||
// Go back to the dashboard
|
||||
os_sched_exit(0);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_ok(bagl_element_t *e) {
|
||||
uint32_t tx = set_result_get_publicKey();
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_cancel(bagl_element_t *e) {
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_ok(bagl_element_t *e) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint8_t signature[100];
|
||||
uint8_t signatureLength;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
uint8_t rLength, sLength, rOffset, sOffset;
|
||||
os_perso_derive_seed_bip32(tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
signatureLength =
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash), signature);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
// Parity is present in the sequence tag in the legacy API
|
||||
G_io_apdu_buffer[0] = 27 + (signature[0] & 0x01);
|
||||
rLength = signature[3];
|
||||
sLength = signature[4 + rLength + 1];
|
||||
rOffset = (rLength == 33 ? 1 : 0);
|
||||
sOffset = (sLength == 33 ? 1 : 0);
|
||||
os_memmove(G_io_apdu_buffer + 1, signature + 4 + rOffset, 32);
|
||||
os_memmove(G_io_apdu_buffer + 1 + 32, signature + 4 + rLength + 2 + sOffset,
|
||||
32);
|
||||
tx = 65;
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(bagl_element_t *e) {
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
void reset(void) {
|
||||
}
|
||||
|
||||
unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
|
||||
switch (channel & ~(IO_FLAGS)) {
|
||||
case CHANNEL_KEYBOARD:
|
||||
break;
|
||||
|
||||
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
|
||||
case CHANNEL_SPI:
|
||||
if (tx_len) {
|
||||
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
|
||||
|
||||
if (channel & IO_RESET_AFTER_REPLIED) {
|
||||
reset();
|
||||
}
|
||||
return 0; // nothing received from the master so far (it's a tx
|
||||
// transaction)
|
||||
} else {
|
||||
return io_seproxyhal_spi_recv(G_io_apdu_buffer,
|
||||
sizeof(G_io_apdu_buffer), 0);
|
||||
}
|
||||
|
||||
default:
|
||||
THROW(INVALID_PARAMETER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_result_get_publicKey() {
|
||||
uint32_t tx = 0;
|
||||
G_io_apdu_buffer[tx++] = 65;
|
||||
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65);
|
||||
tx += 65;
|
||||
G_io_apdu_buffer[tx++] = 40;
|
||||
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40);
|
||||
tx += 40;
|
||||
return tx;
|
||||
}
|
||||
|
||||
void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) {
|
||||
uint8_t tmp[32];
|
||||
os_memset(tmp, 0, 32);
|
||||
os_memmove(tmp + 32 - length, data, length);
|
||||
readu256BE(tmp, target);
|
||||
}
|
||||
|
||||
bool customProcessor(txContext_t *context) {
|
||||
if (context->currentField != TX_RLP_DATA) {
|
||||
return false;
|
||||
}
|
||||
if (context->currentFieldLength != sizeof(daoContext.data)) {
|
||||
screen_printf("Invalid length for RLP_DATA\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize =
|
||||
(context->commandLength <
|
||||
((context->currentFieldLength - context->currentFieldPos))
|
||||
? context->commandLength
|
||||
: context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, daoContext.data + context->currentFieldPos,
|
||||
copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void sample_main(void) {
|
||||
volatile unsigned int rx = 0;
|
||||
volatile unsigned int tx = 0;
|
||||
volatile unsigned int flags = 0;
|
||||
|
||||
// DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only
|
||||
// goal is to retrieve APDU.
|
||||
// When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make
|
||||
// sure the io_event is called with a
|
||||
// switch event, before the apdu is replied to the bootloader. This avoid
|
||||
// APDU injection faults.
|
||||
for (;;) {
|
||||
volatile unsigned short sw = 0;
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
rx = tx;
|
||||
tx = 0; // ensure no race in catch_other if io_exchange throws
|
||||
// an error
|
||||
rx = io_exchange(CHANNEL_APDU | flags, rx);
|
||||
|
||||
// no apdu received, well, reset the session, and reset the
|
||||
// bootloader configuration
|
||||
if (rx == 0) {
|
||||
THROW(0x6982);
|
||||
}
|
||||
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
||||
THROW(0x6E00);
|
||||
}
|
||||
|
||||
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case INS_GET_PUBLIC_KEY: {
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = G_io_apdu_buffer[OFFSET_CDATA];
|
||||
uint8_t p1 = G_io_apdu_buffer[OFFSET_P1];
|
||||
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA + 1;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
screen_printf("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_P2] != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = (dataBuffer[0] << 24) |
|
||||
(dataBuffer[1] << 16) |
|
||||
(dataBuffer[2] << 8) | (dataBuffer[3]);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
os_perso_derive_seed_bip32(bip32Path, bip32PathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32,
|
||||
&privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1,
|
||||
&tmpCtx.publicKeyContext.publicKey,
|
||||
&privateKey, 1);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
getEthAddressStringFromKey(
|
||||
&tmpCtx.publicKeyContext.publicKey,
|
||||
tmpCtx.publicKeyContext.address, &sha3);
|
||||
if (p1 == P1_NON_CONFIRM) {
|
||||
tx = set_result_get_publicKey();
|
||||
THROW(0x9000);
|
||||
} else {
|
||||
os_memmove((unsigned char *)addressSummary,
|
||||
tmpCtx.publicKeyContext.address, 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 5),
|
||||
" ... ", 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 10),
|
||||
tmpCtx.publicKeyContext.address + 40 - 5, 5);
|
||||
addressSummary[15] = '\0';
|
||||
os_memmove((unsigned char *)address1,
|
||||
tmpCtx.publicKeyContext.address, 20);
|
||||
address1[20] = '\0';
|
||||
os_memmove((unsigned char *)address2,
|
||||
tmpCtx.publicKeyContext.address + 20, 20);
|
||||
address2[20] = '\0';
|
||||
uiState = UI_ADDRESS;
|
||||
currentUiElement = 0;
|
||||
uiDone = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
// Pump SPI events until the UI has been displayed, then
|
||||
// go
|
||||
// back to the original event loop
|
||||
while (!uiDone) {
|
||||
unsigned int rx_len;
|
||||
rx_len = io_seproxyhal_spi_recv(
|
||||
G_io_seproxyhal_spi_buffer,
|
||||
sizeof(G_io_seproxyhal_spi_buffer), 0);
|
||||
if (io_seproxyhal_handle_event()) {
|
||||
io_seproxyhal_general_status();
|
||||
continue;
|
||||
}
|
||||
io_event(CHANNEL_SPI);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case INS_ADD_SELF: {
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = G_io_apdu_buffer[OFFSET_CDATA];
|
||||
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA + 1;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
screen_printf("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((G_io_apdu_buffer[OFFSET_P1] != 0) ||
|
||||
(G_io_apdu_buffer[OFFSET_P2] != 0)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = (dataBuffer[0] << 24) |
|
||||
(dataBuffer[1] << 16) |
|
||||
(dataBuffer[2] << 8) | (dataBuffer[3]);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
os_perso_derive_seed_bip32(bip32Path, bip32PathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32,
|
||||
&privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1,
|
||||
&tmpCtx.publicKeyContext.publicKey,
|
||||
&privateKey, 1);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
getEthAddressFromKey(&tmpCtx.publicKeyContext.publicKey,
|
||||
daoContext.selfAddress, &sha3);
|
||||
daoContext.selfAddressProvided = true;
|
||||
THROW(0x9000);
|
||||
} break;
|
||||
|
||||
case INS_SIGN: {
|
||||
uint8_t commandLength = G_io_apdu_buffer[OFFSET_LC];
|
||||
uint8_t *workBuffer = G_io_apdu_buffer + OFFSET_CDATA;
|
||||
parserStatus_e txResult;
|
||||
uint256_t uint256;
|
||||
uint32_t i;
|
||||
uint8_t address[41];
|
||||
if (G_io_apdu_buffer[OFFSET_P1] == P1_FIRST) {
|
||||
tmpCtx.transactionContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
|
||||
(tmpCtx.transactionContext.pathLength >
|
||||
MAX_BIP32_PATH)) {
|
||||
screen_printf("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
commandLength--;
|
||||
for (i = 0; i < tmpCtx.transactionContext.pathLength;
|
||||
i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] =
|
||||
(workBuffer[0] << 24) | (workBuffer[1] << 16) |
|
||||
(workBuffer[2] << 8) | (workBuffer[3]);
|
||||
workBuffer += 4;
|
||||
commandLength -= 4;
|
||||
}
|
||||
initTx(&txContext, &sha3, &txContent, customProcessor,
|
||||
NULL);
|
||||
} else if (G_io_apdu_buffer[OFFSET_P1] != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_P2] != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (txContext.currentField == TX_RLP_NONE) {
|
||||
screen_printf("Parser not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
txResult = processTx(&txContext, workBuffer, commandLength);
|
||||
switch (txResult) {
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
THROW(0x9000);
|
||||
case USTREAM_FAULT:
|
||||
THROW(0x6A80);
|
||||
default:
|
||||
screen_printf("Unexpected parser status\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
|
||||
// Store the hash
|
||||
app_cx_hash((cx_hash_t *)&sha3, CX_LAST,
|
||||
tmpCtx.transactionContext.hash, 0,
|
||||
tmpCtx.transactionContext.hash);
|
||||
// Abort if not sending to the DAO
|
||||
if (os_memcmp(txContent.destination, DAO_ADDRESS, 20) !=
|
||||
0) {
|
||||
screen_printf("Invalid target address\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
// Abort if sending an amount
|
||||
if (txContent.value.length != 0) {
|
||||
screen_printf("Invalid amount\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
// Abort if not calling the transfer function
|
||||
if (os_memcmp(daoContext.data, DAO_TRANSFER_ID, 4) != 0) {
|
||||
screen_printf("Invalid contract call ID\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (daoContext.selfAddressProvided &&
|
||||
os_memcmp(daoContext.selfAddress,
|
||||
daoContext.data + 4 + 12, 20) == 0) {
|
||||
os_memmove((unsigned char *)addressSummary, "Self", 5);
|
||||
address1[0] = '\0';
|
||||
address2[0] = '\0';
|
||||
} else {
|
||||
// Add address
|
||||
getEthAddressStringFromBinary(daoContext.data + 4 + 12,
|
||||
address, &sha3);
|
||||
os_memmove((unsigned char *)addressSummary, address, 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 5),
|
||||
" ... ", 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 10),
|
||||
address + 40 - 5, 5);
|
||||
addressSummary[15] = '\0';
|
||||
os_memmove((unsigned char *)address1, address, 20);
|
||||
address1[20] = '\0';
|
||||
os_memmove((unsigned char *)address2, address + 20, 20);
|
||||
address2[20] = '\0';
|
||||
}
|
||||
// Add token amount
|
||||
convertUint256BE(daoContext.data + 4 + 32, 32, &uint256);
|
||||
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100),
|
||||
100);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[100 + i]) {
|
||||
i++;
|
||||
}
|
||||
adjustDecimals((char *)(G_io_apdu_buffer + 100), i,
|
||||
(char *)G_io_apdu_buffer, 100,
|
||||
DAO_TOKENS_UNIT);
|
||||
i = 0;
|
||||
fullAmount[0] = 'D';
|
||||
fullAmount[1] = 'A';
|
||||
fullAmount[2] = 'O';
|
||||
fullAmount[3] = ' ';
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
fullAmount[4 + i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
fullAmount[4 + i] = '\0';
|
||||
|
||||
uiState = UI_APPROVAL;
|
||||
currentUiElement = 0;
|
||||
uiDone = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
// Pump SPI events until the UI has been displayed, then go
|
||||
// back to the original event loop
|
||||
while (!uiDone) {
|
||||
unsigned int rx_len;
|
||||
rx_len = io_seproxyhal_spi_recv(
|
||||
G_io_seproxyhal_spi_buffer,
|
||||
sizeof(G_io_seproxyhal_spi_buffer), 0);
|
||||
if (io_seproxyhal_handle_event()) {
|
||||
io_seproxyhal_general_status();
|
||||
continue;
|
||||
}
|
||||
io_event(CHANNEL_SPI);
|
||||
}
|
||||
continue;
|
||||
} break;
|
||||
|
||||
case 0xFF: // return to dashboard
|
||||
goto return_to_dashboard;
|
||||
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
switch (e & 0xF000) {
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
os_memset(&txContext, 0, sizeof(txContext));
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
break;
|
||||
}
|
||||
// Unexpected exception => report
|
||||
G_io_apdu_buffer[tx] = sw >> 8;
|
||||
G_io_apdu_buffer[tx + 1] = sw;
|
||||
tx += 2;
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
return_to_dashboard:
|
||||
return;
|
||||
}
|
||||
|
||||
void io_seproxyhal_display(const bagl_element_t *element) {
|
||||
element_displayed = 1;
|
||||
return io_seproxyhal_display_default((bagl_element_t *)element);
|
||||
}
|
||||
|
||||
unsigned char io_event(unsigned char channel) {
|
||||
// nothing done with the event, throw an error on the transport layer if
|
||||
// needed
|
||||
unsigned int offset = 0;
|
||||
|
||||
// can't have more than one tag in the reply, not supported yet.
|
||||
switch (G_io_seproxyhal_spi_buffer[0]) {
|
||||
case SEPROXYHAL_TAG_FINGER_EVENT: {
|
||||
bagl_element_t *elements = NULL;
|
||||
unsigned int elementsSize = 0;
|
||||
if (uiState == UI_IDLE) {
|
||||
elements = (bagl_element_t *)bagl_ui_idle;
|
||||
elementsSize = sizeof(bagl_ui_idle) / sizeof(bagl_element_t);
|
||||
} else if (uiState == UI_ADDRESS) {
|
||||
elements = (bagl_element_t *)bagl_ui_address;
|
||||
elementsSize = sizeof(bagl_ui_address) / sizeof(bagl_element_t);
|
||||
} else if (uiState == UI_APPROVAL) {
|
||||
elements = (bagl_element_t *)bagl_ui_approval;
|
||||
elementsSize = sizeof(bagl_ui_approval) / sizeof(bagl_element_t);
|
||||
}
|
||||
if (elements != NULL) {
|
||||
io_seproxyhal_touch(elements, elementsSize,
|
||||
(G_io_seproxyhal_spi_buffer[4] << 8) |
|
||||
(G_io_seproxyhal_spi_buffer[5] & 0xFF),
|
||||
(G_io_seproxyhal_spi_buffer[6] << 8) |
|
||||
(G_io_seproxyhal_spi_buffer[7] & 0xFF),
|
||||
G_io_seproxyhal_spi_buffer[3]);
|
||||
if (!element_displayed) {
|
||||
goto general_status;
|
||||
}
|
||||
} else {
|
||||
goto general_status;
|
||||
}
|
||||
} break;
|
||||
|
||||
#ifdef HAVE_BLE
|
||||
// Make automatically discoverable again when disconnected
|
||||
|
||||
case SEPROXYHAL_TAG_BLE_CONNECTION_EVENT:
|
||||
if (G_io_seproxyhal_spi_buffer[3] == 0) {
|
||||
// TODO : cleaner reset sequence
|
||||
// first disable BLE before turning it off
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 0;
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4);
|
||||
// send BLE power on (default parameters)
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 3; // ble on & advertise
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 5);
|
||||
}
|
||||
goto general_status;
|
||||
#endif
|
||||
|
||||
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
|
||||
if (uiState == UI_IDLE) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_idle) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_idle[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else if (uiState == UI_ADDRESS) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_address) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_address[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else if (uiState == UI_APPROVAL) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_approval) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_approval[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
screen_printf("Unknown UI state\n");
|
||||
}
|
||||
if (usb_enable_request) {
|
||||
io_usb_enable(1);
|
||||
usb_enable_request = 0;
|
||||
}
|
||||
goto general_status;
|
||||
|
||||
// unknown events are acknowledged
|
||||
default:
|
||||
general_status:
|
||||
// send a general status last command
|
||||
offset = 0;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = SEPROXYHAL_TAG_GENERAL_STATUS;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = 0;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = 2;
|
||||
G_io_seproxyhal_spi_buffer[offset++] =
|
||||
SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND >> 8;
|
||||
G_io_seproxyhal_spi_buffer[offset++] =
|
||||
SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND;
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, offset);
|
||||
element_displayed = 0;
|
||||
break;
|
||||
}
|
||||
// command has been processed, DO NOT reset the current APDU transport
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((section(".boot"))) int main(void) {
|
||||
// exit critical section
|
||||
__asm volatile("cpsie i");
|
||||
|
||||
usb_enable_request = 0;
|
||||
element_displayed = 0;
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
os_memset(&txContext, 0, sizeof(txContext));
|
||||
|
||||
// ensure exception will work as planned
|
||||
os_boot();
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
io_seproxyhal_init();
|
||||
|
||||
#ifdef HAVE_BLE
|
||||
|
||||
// send BLE power on (default parameters)
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 3; // ble on & advertise
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4);
|
||||
#endif
|
||||
|
||||
usb_enable_request = 1;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
|
||||
sample_main();
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
937
src_genericwallet/main.c
Normal file
937
src_genericwallet/main.c
Normal file
@@ -0,0 +1,937 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include <stdbool.h>
|
||||
#include "app_cx_sha3.h"
|
||||
#include "ethUstream.h"
|
||||
#include "ethUtils.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include "os_io_seproxyhal.h"
|
||||
#include "string.h"
|
||||
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
|
||||
|
||||
unsigned char usb_enable_request; // request to turn on USB
|
||||
unsigned char uiDone; // notification to come back to the APDU event loop
|
||||
unsigned int
|
||||
currentUiElement; // currently displayed UI element in a set of elements
|
||||
unsigned char
|
||||
element_displayed; // notification of something displayed in a touch handler
|
||||
|
||||
// UI currently displayed
|
||||
enum UI_STATE { UI_IDLE, UI_ADDRESS, UI_APPROVAL };
|
||||
|
||||
enum UI_STATE uiState;
|
||||
|
||||
void io_usb_enable(unsigned char enabled);
|
||||
void os_boot(void);
|
||||
|
||||
unsigned int io_seproxyhal_touch_exit(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_tx_ok(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_address_ok(bagl_element_t *e);
|
||||
unsigned int io_seproxyhal_touch_address_cancel(bagl_element_t *e);
|
||||
|
||||
uint32_t set_result_get_publicKey(void);
|
||||
|
||||
#define MAX_BIP32_PATH 10
|
||||
|
||||
#define CLA 0xE0
|
||||
#define INS_GET_PUBLIC_KEY 0x02
|
||||
#define INS_SIGN 0x04
|
||||
#define P1_CONFIRM 0x01
|
||||
#define P1_NON_CONFIRM 0x00
|
||||
#define P1_FIRST 0x00
|
||||
#define P1_MORE 0x80
|
||||
|
||||
#define OFFSET_CLA 0
|
||||
#define OFFSET_INS 1
|
||||
#define OFFSET_P1 2
|
||||
#define OFFSET_P2 3
|
||||
#define OFFSET_LC 4
|
||||
#define OFFSET_CDATA 5
|
||||
|
||||
#define WEI_TO_ETHER 18
|
||||
|
||||
typedef struct publicKeyContext_t {
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
uint8_t address[41];
|
||||
} publicKeyContext_t;
|
||||
|
||||
typedef struct transactionContext_t {
|
||||
uint8_t pathLength;
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint8_t hash[32];
|
||||
} transactionContext_t;
|
||||
|
||||
char lineBuffer[50];
|
||||
union {
|
||||
publicKeyContext_t publicKeyContext;
|
||||
transactionContext_t transactionContext;
|
||||
} tmpCtx;
|
||||
txContext_t txContext;
|
||||
txContent_t txContent;
|
||||
app_cx_sha3_t sha3;
|
||||
volatile char addressSummary[21];
|
||||
volatile char address1[21];
|
||||
volatile char address2[21];
|
||||
volatile char fullAmount[50];
|
||||
volatile char gasPrice[50];
|
||||
volatile char startgas[50];
|
||||
|
||||
// blank the screen
|
||||
static const bagl_element_t const bagl_ui_erase_all[] = {
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 60, 320, 420, 0, 0, BAGL_FILL, 0xf9f9f9,
|
||||
0xf9f9f9, 0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
};
|
||||
|
||||
bagl_element_t const bagl_ui_address[] = {
|
||||
// type id x y w h s r fill
|
||||
// fg bg font icon text, out, over, touch
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"Ethereum Wallet",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 35, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0xcccccc, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CANCEL",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_address_cancel,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 165, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CONFIRM",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_address_ok,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 0, 147, 320, 32, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
"Confirm address",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 280, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)addressSummary,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 310, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 330, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
};
|
||||
|
||||
// UI to approve or deny the signature proposal
|
||||
static const bagl_element_t const bagl_ui_approval[] = {
|
||||
|
||||
// type id x y w h s r fill
|
||||
// fg bg font icon text, out, over, touch
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"Ethereum Wallet",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 35, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0xcccccc, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CANCEL",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_tx_cancel,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 165, 385, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"CONFIRM",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_tx_ok,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 0, 87, 320, 32, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
"CONFIRM TRANSACTION",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 125, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)fullAmount,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 175, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)addressSummary,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 205, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 225, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)address2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 265, 320, 32, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
"Gas price / start",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 305, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)gasPrice,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
{{BAGL_LABEL, 0x00, 0, 325, 320, 33, 0, 0, 0, 0x000000, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
||||
(const char *)startgas,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
};
|
||||
|
||||
// UI displayed when no signature proposal has been received
|
||||
static const bagl_element_t const bagl_ui_idle[] = {
|
||||
|
||||
{{BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028, 0x1d2028,
|
||||
0, 0},
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
|
||||
"Ethereum Wallet",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
|
||||
{{BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 190, 215, 120, 40, 0, 6,
|
||||
BAGL_FILL, 0x41ccb4, 0xF9F9F9,
|
||||
BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER |
|
||||
BAGL_FONT_ALIGNMENT_MIDDLE,
|
||||
0},
|
||||
"Exit",
|
||||
0,
|
||||
0x37ae99,
|
||||
0xF9F9F9,
|
||||
(bagl_element_callback_t)io_seproxyhal_touch_exit,
|
||||
NULL,
|
||||
NULL}
|
||||
|
||||
};
|
||||
|
||||
unsigned int io_seproxyhal_touch_exit(bagl_element_t *e) {
|
||||
// Go back to the dashboard
|
||||
os_sched_exit(0);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_ok(bagl_element_t *e) {
|
||||
uint32_t tx = set_result_get_publicKey();
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_cancel(bagl_element_t *e) {
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_ok(bagl_element_t *e) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint8_t signature[100];
|
||||
uint8_t signatureLength;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
uint8_t rLength, sLength, rOffset, sOffset;
|
||||
os_perso_derive_seed_bip32(tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
signatureLength =
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash), signature);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
// Parity is present in the sequence tag in the legacy API
|
||||
G_io_apdu_buffer[0] = 27 + (signature[0] & 0x01);
|
||||
rLength = signature[3];
|
||||
sLength = signature[4 + rLength + 1];
|
||||
rOffset = (rLength == 33 ? 1 : 0);
|
||||
sOffset = (sLength == 33 ? 1 : 0);
|
||||
os_memmove(G_io_apdu_buffer + 1, signature + 4 + rOffset, 32);
|
||||
os_memmove(G_io_apdu_buffer + 1 + 32, signature + 4 + rLength + 2 + sOffset,
|
||||
32);
|
||||
tx = 65;
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(bagl_element_t *e) {
|
||||
uiDone = 1;
|
||||
G_io_apdu_buffer[0] = 0x69;
|
||||
G_io_apdu_buffer[1] = 0x85;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
void reset(void) {
|
||||
}
|
||||
|
||||
unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
|
||||
switch (channel & ~(IO_FLAGS)) {
|
||||
case CHANNEL_KEYBOARD:
|
||||
break;
|
||||
|
||||
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
|
||||
case CHANNEL_SPI:
|
||||
if (tx_len) {
|
||||
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
|
||||
|
||||
if (channel & IO_RESET_AFTER_REPLIED) {
|
||||
reset();
|
||||
}
|
||||
return 0; // nothing received from the master so far (it's a tx
|
||||
// transaction)
|
||||
} else {
|
||||
return io_seproxyhal_spi_recv(G_io_apdu_buffer,
|
||||
sizeof(G_io_apdu_buffer), 0);
|
||||
}
|
||||
|
||||
default:
|
||||
THROW(INVALID_PARAMETER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_result_get_publicKey() {
|
||||
uint32_t tx = 0;
|
||||
G_io_apdu_buffer[tx++] = 65;
|
||||
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65);
|
||||
tx += 65;
|
||||
G_io_apdu_buffer[tx++] = 40;
|
||||
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40);
|
||||
tx += 40;
|
||||
return tx;
|
||||
}
|
||||
|
||||
void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) {
|
||||
uint8_t tmp[32];
|
||||
os_memset(tmp, 0, 32);
|
||||
os_memmove(tmp + 32 - length, data, length);
|
||||
readu256BE(tmp, target);
|
||||
}
|
||||
|
||||
bool customProcessor(txContext_t *context) {
|
||||
if ((context->currentField == TX_RLP_DATA) &&
|
||||
(context->currentFieldLength != 0)) {
|
||||
screen_printf("Data field forbidden\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void sample_main(void) {
|
||||
volatile unsigned int rx = 0;
|
||||
volatile unsigned int tx = 0;
|
||||
volatile unsigned int flags = 0;
|
||||
|
||||
// DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only
|
||||
// goal is to retrieve APDU.
|
||||
// When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make
|
||||
// sure the io_event is called with a
|
||||
// switch event, before the apdu is replied to the bootloader. This avoid
|
||||
// APDU injection faults.
|
||||
for (;;) {
|
||||
volatile unsigned short sw = 0;
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
rx = tx;
|
||||
tx = 0; // ensure no race in catch_other if io_exchange throws
|
||||
// an error
|
||||
rx = io_exchange(CHANNEL_APDU | flags, rx);
|
||||
|
||||
// no apdu received, well, reset the session, and reset the
|
||||
// bootloader configuration
|
||||
if (rx == 0) {
|
||||
THROW(0x6982);
|
||||
}
|
||||
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
||||
THROW(0x6E00);
|
||||
}
|
||||
|
||||
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case INS_GET_PUBLIC_KEY: {
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = G_io_apdu_buffer[OFFSET_CDATA];
|
||||
uint8_t p1 = G_io_apdu_buffer[OFFSET_P1];
|
||||
uint8_t *dataBuffer = G_io_apdu_buffer + OFFSET_CDATA + 1;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
screen_printf("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_P2] != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = (dataBuffer[0] << 24) |
|
||||
(dataBuffer[1] << 16) |
|
||||
(dataBuffer[2] << 8) | (dataBuffer[3]);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
os_perso_derive_seed_bip32(bip32Path, bip32PathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32,
|
||||
&privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1,
|
||||
&tmpCtx.publicKeyContext.publicKey,
|
||||
&privateKey, 1);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
getEthAddressStringFromKey(
|
||||
&tmpCtx.publicKeyContext.publicKey,
|
||||
tmpCtx.publicKeyContext.address, &sha3);
|
||||
if (p1 == P1_NON_CONFIRM) {
|
||||
tx = set_result_get_publicKey();
|
||||
THROW(0x9000);
|
||||
} else {
|
||||
os_memmove((unsigned char *)addressSummary,
|
||||
tmpCtx.publicKeyContext.address, 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 5),
|
||||
" ... ", 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 10),
|
||||
tmpCtx.publicKeyContext.address + 40 - 5, 5);
|
||||
addressSummary[15] = '\0';
|
||||
os_memmove((unsigned char *)address1,
|
||||
tmpCtx.publicKeyContext.address, 20);
|
||||
address1[20] = '\0';
|
||||
os_memmove((unsigned char *)address2,
|
||||
tmpCtx.publicKeyContext.address + 20, 20);
|
||||
address2[20] = '\0';
|
||||
uiState = UI_ADDRESS;
|
||||
currentUiElement = 0;
|
||||
uiDone = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
// Pump SPI events until the UI has been displayed, then
|
||||
// go
|
||||
// back to the original event loop
|
||||
while (!uiDone) {
|
||||
unsigned int rx_len;
|
||||
rx_len = io_seproxyhal_spi_recv(
|
||||
G_io_seproxyhal_spi_buffer,
|
||||
sizeof(G_io_seproxyhal_spi_buffer), 0);
|
||||
if (io_seproxyhal_handle_event()) {
|
||||
io_seproxyhal_general_status();
|
||||
continue;
|
||||
}
|
||||
io_event(CHANNEL_SPI);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case INS_SIGN: {
|
||||
uint8_t commandLength = G_io_apdu_buffer[OFFSET_LC];
|
||||
uint8_t *workBuffer = G_io_apdu_buffer + OFFSET_CDATA;
|
||||
parserStatus_e txResult;
|
||||
uint256_t uint256;
|
||||
uint32_t i;
|
||||
uint8_t address[41];
|
||||
if (G_io_apdu_buffer[OFFSET_P1] == P1_FIRST) {
|
||||
tmpCtx.transactionContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
|
||||
(tmpCtx.transactionContext.pathLength >
|
||||
MAX_BIP32_PATH)) {
|
||||
screen_printf("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
commandLength--;
|
||||
for (i = 0; i < tmpCtx.transactionContext.pathLength;
|
||||
i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] =
|
||||
(workBuffer[0] << 24) | (workBuffer[1] << 16) |
|
||||
(workBuffer[2] << 8) | (workBuffer[3]);
|
||||
workBuffer += 4;
|
||||
commandLength -= 4;
|
||||
}
|
||||
initTx(&txContext, &sha3, &txContent, customProcessor,
|
||||
NULL);
|
||||
} else if (G_io_apdu_buffer[OFFSET_P1] != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_P2] != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (txContext.currentField == TX_RLP_NONE) {
|
||||
screen_printf("Parser not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
txResult = processTx(&txContext, workBuffer, commandLength);
|
||||
switch (txResult) {
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
THROW(0x9000);
|
||||
case USTREAM_FAULT:
|
||||
THROW(0x6A80);
|
||||
default:
|
||||
screen_printf("Unexpected parser status\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
|
||||
// Store the hash
|
||||
app_cx_hash((cx_hash_t *)&sha3, CX_LAST,
|
||||
tmpCtx.transactionContext.hash, 0,
|
||||
tmpCtx.transactionContext.hash);
|
||||
// Add address
|
||||
getEthAddressStringFromBinary(txContent.destination,
|
||||
address, &sha3);
|
||||
os_memmove((unsigned char *)addressSummary, address, 5);
|
||||
os_memmove((unsigned char *)(addressSummary + 5), " ... ",
|
||||
5);
|
||||
os_memmove((unsigned char *)(addressSummary + 10),
|
||||
address + 40 - 5, 5);
|
||||
addressSummary[15] = '\0';
|
||||
os_memmove((unsigned char *)address1, address, 20);
|
||||
address1[20] = '\0';
|
||||
os_memmove((unsigned char *)address2, address + 20, 20);
|
||||
address2[20] = '\0';
|
||||
// Add amount in ethers
|
||||
convertUint256BE(txContent.value.value,
|
||||
txContent.value.length, &uint256);
|
||||
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100),
|
||||
100);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[100 + i]) {
|
||||
i++;
|
||||
}
|
||||
adjustDecimals((char *)(G_io_apdu_buffer + 100), i,
|
||||
(char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
|
||||
i = 0;
|
||||
fullAmount[0] = 'E';
|
||||
fullAmount[1] = 'T';
|
||||
fullAmount[2] = 'H';
|
||||
fullAmount[3] = ' ';
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
fullAmount[4 + i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
fullAmount[4 + i] = '\0';
|
||||
// Add gas price in ethers
|
||||
convertUint256BE(txContent.gasprice.value,
|
||||
txContent.gasprice.length, &uint256);
|
||||
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100),
|
||||
100);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[100 + i]) {
|
||||
i++;
|
||||
}
|
||||
adjustDecimals((char *)(G_io_apdu_buffer + 100), i,
|
||||
(char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
|
||||
i = 0;
|
||||
gasPrice[0] = 'E';
|
||||
gasPrice[1] = 'T';
|
||||
gasPrice[2] = 'H';
|
||||
gasPrice[3] = ' ';
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
gasPrice[4 + i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
gasPrice[4 + i] = '\0';
|
||||
// Add gas limit in native format
|
||||
convertUint256BE(txContent.startgas.value,
|
||||
txContent.startgas.length, &uint256);
|
||||
tostring256(&uint256, 10, (char *)G_io_apdu_buffer, 100);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
startgas[i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
startgas[i] = '\0';
|
||||
|
||||
uiState = UI_APPROVAL;
|
||||
currentUiElement = 0;
|
||||
uiDone = 0;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
// Pump SPI events until the UI has been displayed, then go
|
||||
// back to the original event loop
|
||||
while (!uiDone) {
|
||||
unsigned int rx_len;
|
||||
rx_len = io_seproxyhal_spi_recv(
|
||||
G_io_seproxyhal_spi_buffer,
|
||||
sizeof(G_io_seproxyhal_spi_buffer), 0);
|
||||
if (io_seproxyhal_handle_event()) {
|
||||
io_seproxyhal_general_status();
|
||||
continue;
|
||||
}
|
||||
io_event(CHANNEL_SPI);
|
||||
}
|
||||
continue;
|
||||
} break;
|
||||
|
||||
case 0xFF: // return to dashboard
|
||||
goto return_to_dashboard;
|
||||
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
switch (e & 0xF000) {
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
os_memset(&txContext, 0, sizeof(txContext));
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
break;
|
||||
}
|
||||
// Unexpected exception => report
|
||||
G_io_apdu_buffer[tx] = sw >> 8;
|
||||
G_io_apdu_buffer[tx + 1] = sw;
|
||||
tx += 2;
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
return_to_dashboard:
|
||||
return;
|
||||
}
|
||||
|
||||
void io_seproxyhal_display(const bagl_element_t *element) {
|
||||
element_displayed = 1;
|
||||
return io_seproxyhal_display_default((bagl_element_t *)element);
|
||||
}
|
||||
|
||||
unsigned char io_event(unsigned char channel) {
|
||||
// nothing done with the event, throw an error on the transport layer if
|
||||
// needed
|
||||
unsigned int offset = 0;
|
||||
|
||||
// can't have more than one tag in the reply, not supported yet.
|
||||
switch (G_io_seproxyhal_spi_buffer[0]) {
|
||||
case SEPROXYHAL_TAG_FINGER_EVENT: {
|
||||
bagl_element_t *elements = NULL;
|
||||
unsigned int elementsSize = 0;
|
||||
if (uiState == UI_IDLE) {
|
||||
elements = (bagl_element_t *)bagl_ui_idle;
|
||||
elementsSize = sizeof(bagl_ui_idle) / sizeof(bagl_element_t);
|
||||
} else if (uiState == UI_ADDRESS) {
|
||||
elements = (bagl_element_t *)bagl_ui_address;
|
||||
elementsSize = sizeof(bagl_ui_address) / sizeof(bagl_element_t);
|
||||
} else if (uiState == UI_APPROVAL) {
|
||||
elements = (bagl_element_t *)bagl_ui_approval;
|
||||
elementsSize = sizeof(bagl_ui_approval) / sizeof(bagl_element_t);
|
||||
}
|
||||
if (elements != NULL) {
|
||||
io_seproxyhal_touch(elements, elementsSize,
|
||||
(G_io_seproxyhal_spi_buffer[4] << 8) |
|
||||
(G_io_seproxyhal_spi_buffer[5] & 0xFF),
|
||||
(G_io_seproxyhal_spi_buffer[6] << 8) |
|
||||
(G_io_seproxyhal_spi_buffer[7] & 0xFF),
|
||||
G_io_seproxyhal_spi_buffer[3]);
|
||||
if (!element_displayed) {
|
||||
goto general_status;
|
||||
}
|
||||
} else {
|
||||
goto general_status;
|
||||
}
|
||||
} break;
|
||||
|
||||
#ifdef HAVE_BLE
|
||||
// Make automatically discoverable again when disconnected
|
||||
|
||||
case SEPROXYHAL_TAG_BLE_CONNECTION_EVENT:
|
||||
if (G_io_seproxyhal_spi_buffer[3] == 0) {
|
||||
// TODO : cleaner reset sequence
|
||||
// first disable BLE before turning it off
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 0;
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4);
|
||||
// send BLE power on (default parameters)
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 3; // ble on & advertise
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 5);
|
||||
}
|
||||
goto general_status;
|
||||
#endif
|
||||
|
||||
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
|
||||
if (uiState == UI_IDLE) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_idle) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_idle[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else if (uiState == UI_ADDRESS) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_address) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_address[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else if (uiState == UI_APPROVAL) {
|
||||
if (currentUiElement <
|
||||
(sizeof(bagl_ui_approval) / sizeof(bagl_element_t))) {
|
||||
io_seproxyhal_display(&bagl_ui_approval[currentUiElement++]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
screen_printf("Unknown UI state\n");
|
||||
}
|
||||
if (usb_enable_request) {
|
||||
io_usb_enable(1);
|
||||
usb_enable_request = 0;
|
||||
}
|
||||
goto general_status;
|
||||
|
||||
// unknown events are acknowledged
|
||||
default:
|
||||
general_status:
|
||||
// send a general status last command
|
||||
offset = 0;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = SEPROXYHAL_TAG_GENERAL_STATUS;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = 0;
|
||||
G_io_seproxyhal_spi_buffer[offset++] = 2;
|
||||
G_io_seproxyhal_spi_buffer[offset++] =
|
||||
SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND >> 8;
|
||||
G_io_seproxyhal_spi_buffer[offset++] =
|
||||
SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND;
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, offset);
|
||||
element_displayed = 0;
|
||||
break;
|
||||
}
|
||||
// command has been processed, DO NOT reset the current APDU transport
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((section(".boot"))) int main(void) {
|
||||
// exit critical section
|
||||
__asm volatile("cpsie i");
|
||||
|
||||
usb_enable_request = 0;
|
||||
element_displayed = 0;
|
||||
uiState = UI_IDLE;
|
||||
currentUiElement = 0;
|
||||
os_memset(&txContext, 0, sizeof(txContext));
|
||||
|
||||
// ensure exception will work as planned
|
||||
os_boot();
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
io_seproxyhal_init();
|
||||
|
||||
#ifdef HAVE_BLE
|
||||
|
||||
// send BLE power on (default parameters)
|
||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_RADIO_POWER;
|
||||
G_io_seproxyhal_spi_buffer[1] = 0;
|
||||
G_io_seproxyhal_spi_buffer[2] = 1;
|
||||
G_io_seproxyhal_spi_buffer[3] = 3; // ble on & advertise
|
||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4);
|
||||
#endif
|
||||
|
||||
usb_enable_request = 1;
|
||||
io_seproxyhal_display(&bagl_ui_erase_all[0]);
|
||||
|
||||
sample_main();
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
299
src_tmp/app_cx_sha3.c
Normal file
299
src_tmp/app_cx_sha3.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
#include "app_cx_sha3.h"
|
||||
|
||||
#define S64(x, y) state[x + 5 * y]
|
||||
#define ROTL64(x, n) (((x) << (n)) | ((x) >> ((64) - (n))))
|
||||
#define _64BITS(h, l) (h##ULL << 32) | (l##ULL)
|
||||
|
||||
static void cx_sha3_theta(uint64bits_t state[]) {
|
||||
uint64bits_t C[5];
|
||||
uint64bits_t D[5];
|
||||
C[0] = S64(0, 0) ^ S64(0, 1) ^ S64(0, 2) ^ S64(0, 3) ^ S64(0, 4);
|
||||
C[1] = S64(1, 0) ^ S64(1, 1) ^ S64(1, 2) ^ S64(1, 3) ^ S64(1, 4);
|
||||
C[2] = S64(2, 0) ^ S64(2, 1) ^ S64(2, 2) ^ S64(2, 3) ^ S64(2, 4);
|
||||
C[3] = S64(3, 0) ^ S64(3, 1) ^ S64(3, 2) ^ S64(3, 3) ^ S64(3, 4);
|
||||
C[4] = S64(4, 0) ^ S64(4, 1) ^ S64(4, 2) ^ S64(4, 3) ^ S64(4, 4);
|
||||
|
||||
D[0] = C[4] ^ ROTL64(C[1], 1);
|
||||
D[1] = C[0] ^ ROTL64(C[2], 1);
|
||||
D[2] = C[1] ^ ROTL64(C[3], 1);
|
||||
D[3] = C[2] ^ ROTL64(C[4], 1);
|
||||
D[4] = C[3] ^ ROTL64(C[0], 1);
|
||||
|
||||
S64(0, 0) = S64(0, 0) ^ D[0];
|
||||
S64(1, 0) = S64(1, 0) ^ D[1];
|
||||
S64(2, 0) = S64(2, 0) ^ D[2];
|
||||
S64(3, 0) = S64(3, 0) ^ D[3];
|
||||
S64(4, 0) = S64(4, 0) ^ D[4];
|
||||
|
||||
S64(0, 1) = S64(0, 1) ^ D[0];
|
||||
S64(1, 1) = S64(1, 1) ^ D[1];
|
||||
S64(2, 1) = S64(2, 1) ^ D[2];
|
||||
S64(3, 1) = S64(3, 1) ^ D[3];
|
||||
S64(4, 1) = S64(4, 1) ^ D[4];
|
||||
|
||||
S64(0, 2) = S64(0, 2) ^ D[0];
|
||||
S64(1, 2) = S64(1, 2) ^ D[1];
|
||||
S64(2, 2) = S64(2, 2) ^ D[2];
|
||||
S64(3, 2) = S64(3, 2) ^ D[3];
|
||||
S64(4, 2) = S64(4, 2) ^ D[4];
|
||||
|
||||
S64(0, 3) = S64(0, 3) ^ D[0];
|
||||
S64(1, 3) = S64(1, 3) ^ D[1];
|
||||
S64(2, 3) = S64(2, 3) ^ D[2];
|
||||
S64(3, 3) = S64(3, 3) ^ D[3];
|
||||
S64(4, 3) = S64(4, 3) ^ D[4];
|
||||
|
||||
S64(0, 4) = S64(0, 4) ^ D[0];
|
||||
S64(1, 4) = S64(1, 4) ^ D[1];
|
||||
S64(2, 4) = S64(2, 4) ^ D[2];
|
||||
S64(3, 4) = S64(3, 4) ^ D[3];
|
||||
S64(4, 4) = S64(4, 4) ^ D[4];
|
||||
}
|
||||
|
||||
static void cx_sha3_rho(uint64bits_t state[]) {
|
||||
// S64(0,0) = ROTL(S64(1,0), 0);
|
||||
S64(0, 1) = ROTL64(S64(0, 1), 36);
|
||||
S64(0, 2) = ROTL64(S64(0, 2), 3);
|
||||
S64(0, 3) = ROTL64(S64(0, 3), 41);
|
||||
S64(0, 4) = ROTL64(S64(0, 4), 18);
|
||||
|
||||
S64(1, 0) = ROTL64(S64(1, 0), 1);
|
||||
S64(1, 1) = ROTL64(S64(1, 1), 44);
|
||||
S64(1, 2) = ROTL64(S64(1, 2), 10);
|
||||
S64(1, 3) = ROTL64(S64(1, 3), 45);
|
||||
S64(1, 4) = ROTL64(S64(1, 4), 2);
|
||||
|
||||
S64(2, 0) = ROTL64(S64(2, 0), 62);
|
||||
S64(2, 1) = ROTL64(S64(2, 1), 6);
|
||||
S64(2, 2) = ROTL64(S64(2, 2), 43);
|
||||
S64(2, 3) = ROTL64(S64(2, 3), 15);
|
||||
S64(2, 4) = ROTL64(S64(2, 4), 61);
|
||||
|
||||
S64(3, 0) = ROTL64(S64(3, 0), 28);
|
||||
S64(3, 1) = ROTL64(S64(3, 1), 55);
|
||||
S64(3, 2) = ROTL64(S64(3, 2), 25);
|
||||
S64(3, 3) = ROTL64(S64(3, 3), 21);
|
||||
S64(3, 4) = ROTL64(S64(3, 4), 56);
|
||||
|
||||
S64(4, 0) = ROTL64(S64(4, 0), 27);
|
||||
S64(4, 1) = ROTL64(S64(4, 1), 20);
|
||||
S64(4, 2) = ROTL64(S64(4, 2), 39);
|
||||
S64(4, 3) = ROTL64(S64(4, 3), 8);
|
||||
S64(4, 4) = ROTL64(S64(4, 4), 14);
|
||||
}
|
||||
|
||||
static void cx_sha3_pi(uint64bits_t state[]) {
|
||||
uint64bits_t s;
|
||||
|
||||
s = S64(0, 1);
|
||||
S64(0, 1) = S64(3, 0);
|
||||
S64(3, 0) = S64(3, 3);
|
||||
S64(3, 3) = S64(2, 3);
|
||||
S64(2, 3) = S64(1, 2);
|
||||
S64(1, 2) = S64(2, 1);
|
||||
S64(2, 1) = S64(0, 2);
|
||||
S64(0, 2) = S64(1, 0);
|
||||
S64(1, 0) = S64(1, 1);
|
||||
S64(1, 1) = S64(4, 1);
|
||||
S64(4, 1) = S64(2, 4);
|
||||
S64(2, 4) = S64(4, 2);
|
||||
S64(4, 2) = S64(0, 4);
|
||||
S64(0, 4) = S64(2, 0);
|
||||
S64(2, 0) = S64(2, 2);
|
||||
S64(2, 2) = S64(3, 2);
|
||||
S64(3, 2) = S64(4, 3);
|
||||
S64(4, 3) = S64(3, 4);
|
||||
S64(3, 4) = S64(0, 3);
|
||||
S64(0, 3) = S64(4, 0);
|
||||
S64(4, 0) = S64(4, 4);
|
||||
S64(4, 4) = S64(1, 4);
|
||||
S64(1, 4) = S64(3, 1);
|
||||
S64(3, 1) = S64(1, 3);
|
||||
S64(1, 3) = s;
|
||||
}
|
||||
|
||||
static void cx_sha3_chi(uint64bits_t state[]) {
|
||||
uint64bits_t S0y, S1y;
|
||||
|
||||
S0y = S64(0, 0);
|
||||
S1y = S64(1, 0);
|
||||
S64(0, 0) ^= ~S64(1, 0) & S64(2, 0);
|
||||
S64(1, 0) ^= ~S64(2, 0) & S64(3, 0);
|
||||
S64(2, 0) ^= ~S64(3, 0) & S64(4, 0);
|
||||
S64(3, 0) ^= ~S64(4, 0) & S0y;
|
||||
S64(4, 0) ^= ~S0y & S1y;
|
||||
|
||||
S0y = S64(0, 1);
|
||||
S1y = S64(1, 1);
|
||||
S64(0, 1) ^= ~S64(1, 1) & S64(2, 1);
|
||||
S64(1, 1) ^= ~S64(2, 1) & S64(3, 1);
|
||||
S64(2, 1) ^= ~S64(3, 1) & S64(4, 1);
|
||||
S64(3, 1) ^= ~S64(4, 1) & S0y;
|
||||
S64(4, 1) ^= ~S0y & S1y;
|
||||
|
||||
S0y = S64(0, 2);
|
||||
S1y = S64(1, 2);
|
||||
S64(0, 2) ^= ~S64(1, 2) & S64(2, 2);
|
||||
S64(1, 2) ^= ~S64(2, 2) & S64(3, 2);
|
||||
S64(2, 2) ^= ~S64(3, 2) & S64(4, 2);
|
||||
S64(3, 2) ^= ~S64(4, 2) & S0y;
|
||||
S64(4, 2) ^= ~S0y & S1y;
|
||||
|
||||
S0y = S64(0, 3);
|
||||
S1y = S64(1, 3);
|
||||
S64(0, 3) ^= ~S64(1, 3) & S64(2, 3);
|
||||
S64(1, 3) ^= ~S64(2, 3) & S64(3, 3);
|
||||
S64(2, 3) ^= ~S64(3, 3) & S64(4, 3);
|
||||
S64(3, 3) ^= ~S64(4, 3) & S0y;
|
||||
S64(4, 3) ^= ~S0y & S1y;
|
||||
|
||||
S0y = S64(0, 4);
|
||||
S1y = S64(1, 4);
|
||||
S64(0, 4) ^= ~S64(1, 4) & S64(2, 4);
|
||||
S64(1, 4) ^= ~S64(2, 4) & S64(3, 4);
|
||||
S64(2, 4) ^= ~S64(3, 4) & S64(4, 4);
|
||||
S64(3, 4) ^= ~S64(4, 4) & S0y;
|
||||
S64(4, 4) ^= ~S0y & S1y;
|
||||
}
|
||||
|
||||
static const uint64bits_t WIDE C_cx_iota_RC[24] = {
|
||||
_64BITS(0x00000000, 0x00000001), _64BITS(0x00000000, 0x00008082),
|
||||
_64BITS(0x80000000, 0x0000808A), _64BITS(0x80000000, 0x80008000),
|
||||
_64BITS(0x00000000, 0x0000808B), _64BITS(0x00000000, 0x80000001),
|
||||
_64BITS(0x80000000, 0x80008081), _64BITS(0x80000000, 0x00008009),
|
||||
_64BITS(0x00000000, 0x0000008A), _64BITS(0x00000000, 0x00000088),
|
||||
_64BITS(0x00000000, 0x80008009), _64BITS(0x00000000, 0x8000000A),
|
||||
_64BITS(0x00000000, 0x8000808B), _64BITS(0x80000000, 0x0000008B),
|
||||
_64BITS(0x80000000, 0x00008089), _64BITS(0x80000000, 0x00008003),
|
||||
_64BITS(0x80000000, 0x00008002), _64BITS(0x80000000, 0x00000080),
|
||||
_64BITS(0x00000000, 0x0000800A), _64BITS(0x80000000, 0x8000000A),
|
||||
_64BITS(0x80000000, 0x80008081), _64BITS(0x80000000, 0x00008080),
|
||||
_64BITS(0x00000000, 0x80000001), _64BITS(0x80000000, 0x80008008)};
|
||||
|
||||
static void cx_sha3_iota(uint64bits_t state[], int round) {
|
||||
S64(0, 0) ^= C_cx_iota_RC[round];
|
||||
}
|
||||
|
||||
int app_cx_sha3_init(app_cx_sha3_t *hash, int size) {
|
||||
os_memset(hash, 0, sizeof(app_cx_sha3_t));
|
||||
hash->output_size = size >> 3;
|
||||
hash->block_size = (1600 - 2 * size) >> 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_cx_sha3_block(app_cx_sha3_t *hash) {
|
||||
uint64bits_t *block;
|
||||
uint64bits_t *acc;
|
||||
int r;
|
||||
|
||||
block = (uint64bits_t *)hash->block;
|
||||
acc = (uint64bits_t *)hash->acc;
|
||||
|
||||
acc[0] ^= block[0];
|
||||
acc[1] ^= block[1];
|
||||
acc[2] ^= block[2];
|
||||
acc[3] ^= block[3];
|
||||
acc[4] ^= block[4];
|
||||
acc[5] ^= block[5];
|
||||
acc[6] ^= block[6];
|
||||
acc[7] ^= block[7];
|
||||
acc[8] ^= block[8];
|
||||
if (hash->block_size > 72) {
|
||||
acc[9] ^= block[9];
|
||||
acc[10] ^= block[10];
|
||||
acc[11] ^= block[11];
|
||||
acc[12] ^= block[12];
|
||||
if (hash->block_size > 104) {
|
||||
acc[13] ^= block[13];
|
||||
acc[14] ^= block[14];
|
||||
acc[15] ^= block[15];
|
||||
acc[16] ^= block[16];
|
||||
if (hash->block_size > 136) {
|
||||
acc[17] ^= block[17];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (r = 0; r < 24; r++) {
|
||||
cx_sha3_theta(acc);
|
||||
cx_sha3_rho(acc);
|
||||
cx_sha3_pi(acc);
|
||||
cx_sha3_chi(acc);
|
||||
cx_sha3_iota(acc, r);
|
||||
}
|
||||
}
|
||||
|
||||
int app_cx_hash(cx_hash_t *hash, int mode, unsigned char WIDE *in, int len,
|
||||
unsigned char *out) {
|
||||
unsigned int r;
|
||||
unsigned char block_size;
|
||||
unsigned char *block;
|
||||
int blen;
|
||||
unsigned char *acc;
|
||||
|
||||
// --- init locals ---
|
||||
block_size = 0;
|
||||
blen = 0;
|
||||
block = NULL;
|
||||
acc = NULL;
|
||||
|
||||
block_size = ((app_cx_sha3_t *)hash)->block_size;
|
||||
block = ((app_cx_sha3_t *)hash)->block;
|
||||
blen = ((app_cx_sha3_t *)hash)->blen;
|
||||
((app_cx_sha3_t *)hash)->blen = 0;
|
||||
acc = (unsigned char *)((app_cx_sha3_t *)hash)->acc;
|
||||
|
||||
// --- append input data and process all blocks ---
|
||||
if ((blen + len) >= block_size) {
|
||||
r = block_size - blen;
|
||||
do {
|
||||
os_memmove(block + blen, in, r);
|
||||
app_cx_sha3_block((app_cx_sha3_t *)hash);
|
||||
blen = 0;
|
||||
hash->counter++;
|
||||
in += r;
|
||||
len -= r;
|
||||
r = block_size;
|
||||
} while (len >= block_size);
|
||||
}
|
||||
|
||||
// --- remainder ---
|
||||
os_memmove(block + blen, in, len);
|
||||
blen += len;
|
||||
((app_cx_sha3_t *)hash)->blen = blen;
|
||||
|
||||
// --- last block ---
|
||||
if (mode & CX_LAST) {
|
||||
os_memset(block + blen, 0, (200 - blen));
|
||||
block[blen] |= (hash->algo == CX_SHA3 ? 0x06 : 0x01);
|
||||
block[block_size - 1] |= 0x80;
|
||||
app_cx_sha3_block((app_cx_sha3_t *)hash);
|
||||
// provide result
|
||||
len = ((cx_sha3_t *)hash)->output_size;
|
||||
if (out) {
|
||||
os_memmove(out, acc, len);
|
||||
}
|
||||
((app_cx_sha3_t *)hash)->blen = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
41
src_tmp/app_cx_sha3.h
Normal file
41
src_tmp/app_cx_sha3.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Blue
|
||||
* (c) 2016 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
********************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
struct app_cx_sha3_s {
|
||||
struct cx_hash_header_s header;
|
||||
|
||||
// x bytes per input block, depends on sha3-xxx output size
|
||||
unsigned int output_size;
|
||||
unsigned char block_size;
|
||||
//
|
||||
int blen;
|
||||
unsigned char block[200];
|
||||
// use 64bits type to ensure alignment
|
||||
uint64bits_t acc[25];
|
||||
// unsigned char acc[200];
|
||||
};
|
||||
typedef struct app_cx_sha3_s app_cx_sha3_t;
|
||||
|
||||
int app_cx_sha3_init(app_cx_sha3_t *hash, int size);
|
||||
void app_cx_sha3_block(app_cx_sha3_t *hash);
|
||||
int app_cx_hash(cx_hash_t *hash, int mode, unsigned char WIDE *in, int len,
|
||||
unsigned char *out);
|
||||
157
src_usb/STM32_USB_Device_Library/Class/HID/Inc/usbd_customhid.h
Normal file
157
src_usb/STM32_USB_Device_Library/Class/HID/Inc/usbd_customhid.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_customhid.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.2.0
|
||||
* @date 13-June-2014
|
||||
* @brief header file for the usbd_customhid.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_CUSTOM_HID_CORE_H_
|
||||
#define __USB_CUSTOM_HID_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID
|
||||
* @brief This file is the Header file for USBD_custom_hid.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define CUSTOM_HID_EPIN_ADDR 0x82
|
||||
#define CUSTOM_HID_EPIN_SIZE 0x40
|
||||
|
||||
#define CUSTOM_HID_EPOUT_ADDR 0x02
|
||||
#define CUSTOM_HID_EPOUT_SIZE 0x40
|
||||
|
||||
//#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 75
|
||||
//#define USB_CUSTOM_HID_DESC_SIZ 9
|
||||
|
||||
#define CUSTOM_HID_DESCRIPTOR_TYPE 0x21
|
||||
#define CUSTOM_HID_REPORT_DESC 0x22
|
||||
|
||||
|
||||
#define CUSTOM_HID_REQ_SET_PROTOCOL 0x0B
|
||||
#define CUSTOM_HID_REQ_GET_PROTOCOL 0x03
|
||||
|
||||
#define CUSTOM_HID_REQ_SET_IDLE 0x0A
|
||||
#define CUSTOM_HID_REQ_GET_IDLE 0x02
|
||||
|
||||
#define CUSTOM_HID_REQ_SET_REPORT 0x09
|
||||
#define CUSTOM_HID_REQ_GET_REPORT 0x01
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CUSTOM_HID_IDLE = 0,
|
||||
CUSTOM_HID_BUSY,
|
||||
}
|
||||
CUSTOM_HID_StateTypeDef;
|
||||
|
||||
typedef int8_t (* HIDInit_t) (void);
|
||||
typedef int8_t (* HIDOutEvent_t) (uint8_t* hid_report);
|
||||
typedef int8_t (* HIDDeInit_t) (void);
|
||||
|
||||
typedef struct _USBD_CUSTOM_HID_Itf
|
||||
{
|
||||
HIDInit_t Init;
|
||||
HIDDeInit_t DeInit;
|
||||
HIDOutEvent_t OutEvent;
|
||||
|
||||
}USBD_CUSTOM_HID_ItfTypeDef;
|
||||
|
||||
#include "usbd_customhid_if_template.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//uint8_t Report_buf[USBD_CUSTOM_HID_OUTREPORT_BUF_SIZE];
|
||||
uint32_t Protocol;
|
||||
uint32_t IdleState;
|
||||
uint32_t AltSetting;
|
||||
uint32_t IsReportAvailable;
|
||||
CUSTOM_HID_StateTypeDef state;
|
||||
}
|
||||
USBD_CUSTOM_HID_HandleTypeDef;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern const USBD_ClassTypeDef USBD_CUSTOM_HID;
|
||||
#define USBD_CUSTOM_HID_CLASS &USBD_CUSTOM_HID
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
uint8_t USBD_CUSTOM_HID_SendReport (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *report,
|
||||
uint16_t len);
|
||||
|
||||
|
||||
|
||||
uint8_t USBD_CUSTOM_HID_RegisterInterface (USBD_HandleTypeDef *pdev,
|
||||
USBD_CUSTOM_HID_ItfTypeDef *fops);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __USB_CUSTOM_HID_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
913
src_usb/STM32_USB_Device_Library/Class/HID/Src/usbd_customhid.c
Normal file
913
src_usb/STM32_USB_Device_Library/Class/HID/Src/usbd_customhid.c
Normal file
@@ -0,0 +1,913 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_customhid.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.2.0
|
||||
* @date 13-June-2014
|
||||
* @brief This file provides the CUSTOM_HID core functions.
|
||||
*
|
||||
* @verbatim
|
||||
*
|
||||
* ===================================================================
|
||||
* CUSTOM_HID Class Description
|
||||
* ===================================================================
|
||||
* This module manages the CUSTOM_HID class V1.11 following the "Device Class Definition
|
||||
* for Human Interface Devices (CUSTOM_HID) Version 1.11 Jun 27, 2001".
|
||||
* This driver implements the following aspects of the specification:
|
||||
* - The Boot Interface Subclass
|
||||
* - Usage Page : Generic Desktop
|
||||
* - Usage : Vendor
|
||||
* - Collection : Application
|
||||
*
|
||||
* @note In HS mode and when the DMA is used, all variables and data structures
|
||||
* dealing with the DMA during the transaction process should be 32-bit aligned.
|
||||
*
|
||||
*
|
||||
* @endverbatim
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_customhid.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_ctlreq.h"
|
||||
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
uint8_t *USBD_HID_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_ManufacturerStrDescriptor (USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_ProductStrDescriptor (USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_HID_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
#ifdef USB_SUPPORT_USER_STRING_DESC
|
||||
uint8_t *USBD_HID_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
|
||||
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
||||
|
||||
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);
|
||||
static void Get_SerialNum(void);
|
||||
|
||||
|
||||
static uint8_t USBD_CUSTOM_HID_Init (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_CUSTOM_HID_DeInit (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_CUSTOM_HID_Setup (USBD_HandleTypeDef *pdev,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static uint8_t *USBD_CUSTOM_HID_GetCfgDesc (uint16_t *length);
|
||||
|
||||
static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc (uint16_t *length);
|
||||
|
||||
static uint8_t USBD_CUSTOM_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
|
||||
static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t* hid_report);
|
||||
static uint8_t USBD_CUSTOM_HID_EP0_RxReady (USBD_HandleTypeDef *pdev);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
const USBD_ClassTypeDef const USBD_CUSTOM_HID =
|
||||
{
|
||||
USBD_CUSTOM_HID_Init,
|
||||
USBD_CUSTOM_HID_DeInit,
|
||||
USBD_CUSTOM_HID_Setup,
|
||||
NULL, /*EP0_TxSent*/
|
||||
USBD_CUSTOM_HID_EP0_RxReady, /*EP0_RxReady*/ /* STATUS STAGE IN */
|
||||
USBD_CUSTOM_HID_DataIn, /*DataIn*/
|
||||
USBD_CUSTOM_HID_DataOut,
|
||||
NULL, /*SOF */
|
||||
NULL,
|
||||
NULL,
|
||||
USBD_CUSTOM_HID_GetCfgDesc,
|
||||
USBD_CUSTOM_HID_GetCfgDesc,
|
||||
USBD_CUSTOM_HID_GetCfgDesc,
|
||||
USBD_CUSTOM_HID_GetDeviceQualifierDesc,
|
||||
};
|
||||
|
||||
|
||||
#define USBD_VID 0x2C97
|
||||
#define USBD_PID 0x0000
|
||||
#define USBD_LANGID_STRING 0x409
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
const uint8_t const USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC]=
|
||||
{
|
||||
USB_LEN_LANGID_STR_DESC,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(USBD_LANGID_STRING),
|
||||
HIBYTE(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
const uint8_t const USB_SERIAL_STRING[] =
|
||||
{
|
||||
0x2,
|
||||
USB_DESC_TYPE_STRING,
|
||||
};
|
||||
|
||||
const uint8_t const USBD_MANUFACTURER_STRING[] = {
|
||||
6*2+2,
|
||||
USB_DESC_TYPE_STRING,
|
||||
'L', 0,
|
||||
'e', 0,
|
||||
'd', 0,
|
||||
'g', 0,
|
||||
'e', 0,
|
||||
'r', 0,
|
||||
};
|
||||
|
||||
const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
||||
11*2+2,
|
||||
USB_DESC_TYPE_STRING,
|
||||
'L', 0,
|
||||
'e', 0,
|
||||
'd', 0,
|
||||
'g', 0,
|
||||
'e', 0,
|
||||
'r', 0,
|
||||
' ', 0,
|
||||
'B', 0,
|
||||
'l', 0,
|
||||
'u', 0,
|
||||
'e', 0,
|
||||
};
|
||||
#define USBD_INTERFACE_FS_STRING USBD_PRODUCT_FS_STRING
|
||||
#define USBD_CONFIGURATION_FS_STRING USBD_PRODUCT_FS_STRING
|
||||
|
||||
|
||||
#ifdef HAVE_IO_USB_CDC
|
||||
/* USB CUSTOM_HID device Configuration Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t const USBD_CUSTOM_HID_CfgDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
USB_CUSTOM_HID_CONFIG_DESC_SIZ,
|
||||
/* wTotalLength: Bytes returned */
|
||||
0x00,
|
||||
0x02, /*bNumInterfaces: 1 interface*/
|
||||
0x01, /*bConfigurationValue: Configuration value*/
|
||||
0x00, /*iConfiguration: Index of string descriptor describing
|
||||
the configuration*/
|
||||
0xC0, /*bmAttributes: bus powered */
|
||||
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
|
||||
|
||||
/************** Descriptor of CUSTOM CDC interface association ****/
|
||||
0x08,
|
||||
11, // interface association
|
||||
0, // start at interface 0
|
||||
2, // 2 interfaces
|
||||
2, // class communications
|
||||
2, // abstract(modem)
|
||||
0, // nowrapping
|
||||
0, // iInterfaceAssociation
|
||||
|
||||
/************** Descriptor of CUSTOM HID interface ****************/
|
||||
/* 09 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
|
||||
0x00, /*bInterfaceNumber: Number of Interface*/
|
||||
0x00, /*bAlternateSetting: Alternate setting*/
|
||||
0x01, /*bNumEndpoints*/
|
||||
0x02, /*bInterfaceClass: CDC*/
|
||||
0x02,
|
||||
0x00,
|
||||
0, /*iInterface: Index of string descriptor*/
|
||||
|
||||
0x05,
|
||||
0x24,
|
||||
0x00,
|
||||
0x10,
|
||||
0x01,
|
||||
|
||||
0x05,
|
||||
0x24,
|
||||
0x01,
|
||||
0x00,
|
||||
0x01,
|
||||
|
||||
0x04,
|
||||
0x24,
|
||||
0x02,
|
||||
//0x02, // supported set line state
|
||||
0x00, // don't supported set line state
|
||||
|
||||
0x05,
|
||||
0x24,
|
||||
0x06,
|
||||
0x00,
|
||||
0x01,
|
||||
|
||||
0x07,
|
||||
USB_DESC_TYPE_ENDPOINT,
|
||||
0x83,
|
||||
0x03,
|
||||
0x08, // length ep low
|
||||
0x00, // length ep high
|
||||
0x08,
|
||||
|
||||
|
||||
|
||||
/************** Descriptor of CUSTOM HID interface ****************/
|
||||
/* 09 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
|
||||
0x01, /*bInterfaceNumber: Number of Interface*/
|
||||
0x00, /*bAlternateSetting: Alternate setting*/
|
||||
0x02, /*bNumEndpoints*/
|
||||
0x0A, /*bInterfaceClass: CUSTOM_HID*/
|
||||
0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
||||
0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
||||
0, /*iInterface: Index of string descriptor*/
|
||||
|
||||
|
||||
0x07,
|
||||
USB_DESC_TYPE_ENDPOINT,
|
||||
CUSTOM_HID_EPIN_ADDR,
|
||||
0x02,
|
||||
CUSTOM_HID_EPIN_SIZE, // length ep low
|
||||
0x00, // length ep high
|
||||
0x00,
|
||||
|
||||
0x07,
|
||||
USB_DESC_TYPE_ENDPOINT,
|
||||
CUSTOM_HID_EPOUT_ADDR,
|
||||
0x02,
|
||||
CUSTOM_HID_EPOUT_SIZE, // length ep low
|
||||
0x00, // length ep high
|
||||
0x00,
|
||||
|
||||
} ;
|
||||
#else
|
||||
const uint8_t const CUSTOM_HID_ReportDesc[] = {
|
||||
0x06, 0xA0, 0xFF, // Usage page (vendor defined)
|
||||
0x09, 0x01, // Usage ID (vendor defined)
|
||||
0xA1, 0x01, // Collection (application)
|
||||
|
||||
// The Input report
|
||||
0x09, 0x03, // Usage ID - vendor defined
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8 bits)
|
||||
0x95, CUSTOM_HID_EPIN_SIZE, // Report Count (64 fields)
|
||||
0x81, 0x08, // Input (Data, Variable, Absolute)
|
||||
|
||||
// The Output report
|
||||
0x09, 0x04, // Usage ID - vendor defined
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8 bits)
|
||||
0x95, CUSTOM_HID_EPOUT_SIZE, // Report Count (64 fields)
|
||||
0x91, 0x08, // Output (Data, Variable, Absolute)
|
||||
0xC0
|
||||
};
|
||||
|
||||
/* USB CUSTOM_HID device Configuration Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t const USBD_CUSTOM_HID_CfgDesc[] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
0x29,
|
||||
/* wTotalLength: Bytes returned */
|
||||
0x00,
|
||||
0x01, /*bNumInterfaces: 1 interface*/
|
||||
0x01, /*bConfigurationValue: Configuration value*/
|
||||
0x00, /*iConfiguration: Index of string descriptor describing
|
||||
the configuration*/
|
||||
0xC0, /*bmAttributes: bus powered */
|
||||
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
|
||||
|
||||
/************** Descriptor of CUSTOM HID interface ****************/
|
||||
/* 09 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
|
||||
0x00, /*bInterfaceNumber: Number of Interface*/
|
||||
0x00, /*bAlternateSetting: Alternate setting*/
|
||||
0x02, /*bNumEndpoints*/
|
||||
0x03, /*bInterfaceClass: CUSTOM_HID*/
|
||||
0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
||||
0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
||||
0, /*iInterface: Index of string descriptor*/
|
||||
/******************** Descriptor of CUSTOM_HID *************************/
|
||||
/* 18 */
|
||||
0x09, /*bLength: CUSTOM_HID Descriptor size*/
|
||||
CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/
|
||||
0x11, /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/
|
||||
0x01,
|
||||
0x00, /*bCountryCode: Hardware target country*/
|
||||
0x01, /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
|
||||
0x22, /*bDescriptorType*/
|
||||
sizeof(CUSTOM_HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
||||
0x00,
|
||||
/******************** Descriptor of Custom HID endpoints ********************/
|
||||
/* 27 */
|
||||
0x07, /*bLength: Endpoint Descriptor size*/
|
||||
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
|
||||
CUSTOM_HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
|
||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
||||
CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
|
||||
0x00,
|
||||
0x01, /*bInterval: Polling Interval (20 ms)*/
|
||||
/* 34 */
|
||||
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
CUSTOM_HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */
|
||||
0x00,
|
||||
0x01, /* bInterval: Polling Interval (20 ms) */
|
||||
/* 41 */
|
||||
} ;
|
||||
#endif // HAVE_IO_USB_CDC
|
||||
|
||||
/* USB CUSTOM_HID device Configuration Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t const USBD_CUSTOM_HID_Desc[] __ALIGN_END =
|
||||
{
|
||||
/* 18 */
|
||||
0x09, /*bLength: CUSTOM_HID Descriptor size*/
|
||||
CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/
|
||||
0x11, /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/
|
||||
0x01,
|
||||
0x00, /*bCountryCode: Hardware target country*/
|
||||
0x01, /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
|
||||
0x22, /*bDescriptorType*/
|
||||
sizeof(CUSTOM_HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t const USBD_CUSTOM_HID_DeviceQualifierDesc[] __ALIGN_END =
|
||||
{
|
||||
USB_LEN_DEV_QUALIFIER_DESC,
|
||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
const USBD_DescriptorsTypeDef const HID_Desc = {
|
||||
USBD_HID_DeviceDescriptor,
|
||||
USBD_HID_LangIDStrDescriptor,
|
||||
USBD_HID_ManufacturerStrDescriptor,
|
||||
USBD_HID_ProductStrDescriptor,
|
||||
USBD_HID_SerialStrDescriptor,
|
||||
USBD_HID_ConfigStrDescriptor,
|
||||
USBD_HID_InterfaceStrDescriptor,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
const uint8_t const USBD_DeviceDesc[USB_LEN_DEV_DESC]= {
|
||||
0x12, /* bLength */
|
||||
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
||||
0x00, /* bcdUSB */
|
||||
0x02,
|
||||
0x00, /* bDeviceClass */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
||||
LOBYTE(USBD_VID), /* idVendor */
|
||||
HIBYTE(USBD_VID), /* idVendor */
|
||||
LOBYTE(USBD_PID), /* idVendor */
|
||||
HIBYTE(USBD_PID), /* idVendor */
|
||||
0x00, /* bcdDevice rel. 2.00 */
|
||||
0x02,
|
||||
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
||||
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
||||
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
||||
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
|
||||
}; /* USB_DeviceDescriptor */
|
||||
|
||||
|
||||
USBD_CUSTOM_HID_HandleTypeDef custom_hid_ClassData;
|
||||
|
||||
/**
|
||||
* @brief Returns the device descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_DeviceDesc);
|
||||
return (uint8_t*)USBD_DeviceDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the LangID string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_LangIDDesc);
|
||||
return (uint8_t*)USBD_LangIDDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the product string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_PRODUCT_FS_STRING);
|
||||
return USBD_PRODUCT_FS_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the manufacturer string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_MANUFACTURER_STRING);
|
||||
return USBD_MANUFACTURER_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the serial number string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USB_SERIAL_STRING);
|
||||
return USB_SERIAL_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the configuration string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_CONFIGURATION_FS_STRING);
|
||||
return USBD_CONFIGURATION_FS_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the interface string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_HID_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_INTERFACE_FS_STRING);
|
||||
return USBD_INTERFACE_FS_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert Hex 32Bits value into char
|
||||
* @param value: value to convert
|
||||
* @param pbuf: pointer to the buffer
|
||||
* @param len: buffer length
|
||||
* @retval None
|
||||
*/
|
||||
static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
|
||||
for( idx = 0 ; idx < len ; idx ++)
|
||||
{
|
||||
if( ((value >> 28)) < 0xA )
|
||||
{
|
||||
pbuf[ 2* idx] = (value >> 28) + '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pbuf[2* idx] = (value >> 28) + 'A' - 10;
|
||||
}
|
||||
|
||||
value = value << 4;
|
||||
|
||||
pbuf[ 2* idx + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CUSTOM_HID_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_Init
|
||||
* Initialize the CUSTOM_HID interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CUSTOM_HID_Init (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
USBD_CUSTOM_HID_HandleTypeDef* hhid;
|
||||
|
||||
/*
|
||||
USBD_LL_OpenEP(pdev,
|
||||
0x83,
|
||||
USBD_EP_TYPE_BULK,
|
||||
8);
|
||||
*/
|
||||
|
||||
/* Open EP IN */
|
||||
USBD_LL_OpenEP(pdev,
|
||||
CUSTOM_HID_EPIN_ADDR,
|
||||
USBD_EP_TYPE_BULK,
|
||||
CUSTOM_HID_EPIN_SIZE);
|
||||
|
||||
/* Open EP OUT */
|
||||
USBD_LL_OpenEP(pdev,
|
||||
CUSTOM_HID_EPOUT_ADDR,
|
||||
USBD_EP_TYPE_BULK,
|
||||
CUSTOM_HID_EPOUT_SIZE);
|
||||
|
||||
|
||||
pdev->pClassData = &custom_hid_ClassData; //USBD_malloc(sizeof (USBD_CUSTOM_HID_HandleTypeDef));
|
||||
|
||||
if(pdev->pClassData == NULL)
|
||||
{
|
||||
return USBD_FAIL;
|
||||
}
|
||||
|
||||
hhid = pdev->pClassData;
|
||||
|
||||
hhid->state = CUSTOM_HID_IDLE;
|
||||
((HIDInit_t)PIC(((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->Init))();
|
||||
/* Prepare Out endpoint to receive 1st packet */
|
||||
USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR, USBD_CUSTOM_HID_OUTREPORT_BUF_SIZE);
|
||||
|
||||
/* garbles the usb com visibly
|
||||
// transmit a first empty reply on the IN endpoint
|
||||
USBD_LL_Transmit (pdev,
|
||||
CUSTOM_HID_EPIN_ADDR,
|
||||
NULL,
|
||||
0);
|
||||
*/
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_Init
|
||||
* DeInitialize the CUSTOM_HID layer
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CUSTOM_HID_DeInit (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
/* Close CUSTOM_HID EP IN */
|
||||
USBD_LL_CloseEP(pdev,
|
||||
CUSTOM_HID_EPIN_ADDR);
|
||||
|
||||
/* Close CUSTOM_HID EP OUT */
|
||||
USBD_LL_CloseEP(pdev,
|
||||
CUSTOM_HID_EPOUT_ADDR);
|
||||
|
||||
/* FRee allocated memory */
|
||||
if(pdev->pClassData != NULL)
|
||||
{
|
||||
((HIDDeInit_t)PIC(((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->DeInit))();
|
||||
//USBD_free(pdev->pClassData);
|
||||
pdev->pClassData = NULL;
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_Setup
|
||||
* Handle the CUSTOM_HID specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CUSTOM_HID_Setup (USBD_HandleTypeDef *pdev,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
uint8_t *pbuf = NULL;
|
||||
USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData;
|
||||
|
||||
#ifdef HAVE_IO_USB_CDC
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case 0x20:
|
||||
USBD_CtlPrepareRx (pdev, hhid->Report_buf, (uint8_t)(req->wLength));
|
||||
case 0x22:
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
}
|
||||
#else
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
switch (req->bRequest)
|
||||
{
|
||||
|
||||
|
||||
case CUSTOM_HID_REQ_SET_PROTOCOL:
|
||||
hhid->Protocol = (uint8_t)(req->wValue);
|
||||
break;
|
||||
|
||||
case CUSTOM_HID_REQ_GET_PROTOCOL:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&hhid->Protocol,
|
||||
1);
|
||||
break;
|
||||
|
||||
case CUSTOM_HID_REQ_SET_IDLE:
|
||||
hhid->IdleState = (uint8_t)(req->wValue >> 8);
|
||||
break;
|
||||
|
||||
case CUSTOM_HID_REQ_GET_IDLE:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&hhid->IdleState,
|
||||
1);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
if( req->wValue >> 8 == CUSTOM_HID_REPORT_DESC)
|
||||
{
|
||||
len = MIN(sizeof(CUSTOM_HID_ReportDesc) , req->wLength);
|
||||
pbuf = CUSTOM_HID_ReportDesc;
|
||||
}
|
||||
else if( req->wValue >> 8 == CUSTOM_HID_DESCRIPTOR_TYPE)
|
||||
{
|
||||
pbuf = USBD_CUSTOM_HID_Desc;
|
||||
len = MIN(sizeof(USBD_CUSTOM_HID_Desc) , req->wLength);
|
||||
}
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
pbuf,
|
||||
len);
|
||||
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_INTERFACE :
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&hhid->AltSetting,
|
||||
1);
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE :
|
||||
hhid->AltSetting = (uint8_t)(req->wValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_IO_USB_CDC
|
||||
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_SendReport
|
||||
* Send CUSTOM_HID Report
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to report
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_CUSTOM_HID_SendReport (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *report,
|
||||
uint16_t len)
|
||||
{
|
||||
USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData;
|
||||
|
||||
if (pdev->dev_state == USBD_STATE_CONFIGURED )
|
||||
{
|
||||
/*
|
||||
if(hhid->state == CUSTOM_HID_IDLE)
|
||||
{
|
||||
hhid->state = CUSTOM_HID_BUSY;
|
||||
*/
|
||||
USBD_LL_Transmit (pdev,
|
||||
CUSTOM_HID_EPIN_ADDR,
|
||||
report,
|
||||
len);
|
||||
//}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_GetCfgDesc
|
||||
* return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_CUSTOM_HID_GetCfgDesc (uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_CUSTOM_HID_CfgDesc);
|
||||
return USBD_CUSTOM_HID_CfgDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_DataIn
|
||||
* handle data IN Stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CUSTOM_HID_DataIn (USBD_HandleTypeDef *pdev,
|
||||
uint8_t epnum)
|
||||
{
|
||||
|
||||
/* Ensure that the FIFO is empty before a new transfer, this condition could
|
||||
be caused by a new transfer before the end of the previous transfer */
|
||||
((USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData)->state = CUSTOM_HID_IDLE;
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_DataOut
|
||||
* handle data OUT Stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev,
|
||||
uint8_t epnum, uint8_t* buffer)
|
||||
{
|
||||
|
||||
USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData;
|
||||
|
||||
USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR , USBD_CUSTOM_HID_OUTREPORT_BUF_SIZE);
|
||||
|
||||
((HIDOutEvent_t)PIC(((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent))(buffer);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_EP0_RxReady
|
||||
* Handles control request data.
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
USBD_CUSTOM_HID_HandleTypeDef *hhid = pdev->pClassData;
|
||||
|
||||
if (hhid->IsReportAvailable == 1)
|
||||
{
|
||||
((HIDOutEvent_t)PIC(((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent))(NULL);
|
||||
hhid->IsReportAvailable = 0;
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeviceQualifierDescriptor
|
||||
* return Device Qualifier descriptor
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc (uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_CUSTOM_HID_DeviceQualifierDesc);
|
||||
return USBD_CUSTOM_HID_DeviceQualifierDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CUSTOM_HID_RegisterInterface
|
||||
* @param pdev: device instance
|
||||
* @param fops: CUSTOMHID Interface callback
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_CUSTOM_HID_RegisterInterface (USBD_HandleTypeDef *pdev,
|
||||
USBD_CUSTOM_HID_ItfTypeDef *fops)
|
||||
{
|
||||
uint8_t ret = USBD_FAIL;
|
||||
|
||||
if(fops != NULL)
|
||||
{
|
||||
pdev->pUserData= fops;
|
||||
ret = USBD_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
169
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_conf_template.h
Normal file
169
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_conf_template.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_conf_template.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief Header file for the usbd_conf_template.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CONF_TEMPLATE_H
|
||||
#define __USBD_CONF_TEMPLATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32fxxx.h" /* replace 'stm32xxx' with your HAL driver header filename, ex: stm32f4xx.h */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF
|
||||
* @brief USB device low level driver configuration file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define USBD_MAX_NUM_INTERFACES 1
|
||||
#define USBD_MAX_NUM_CONFIGURATION 1
|
||||
#define USBD_MAX_STR_DESC_SIZ 0x100
|
||||
#define USBD_SUPPORT_USER_STRING 0
|
||||
#define USBD_SELF_POWERED 1
|
||||
#define USBD_DEBUG_LEVEL 2
|
||||
|
||||
/* MSC Class Config */
|
||||
#define MSC_MEDIA_PACKET 8192
|
||||
|
||||
/* CDC Class Config */
|
||||
#define USBD_CDC_INTERVAL 2000
|
||||
|
||||
/* DFU Class Config */
|
||||
#define USBD_DFU_MAX_ITF_NUM 1
|
||||
#define USBD_DFU_XFERS_IZE 1024
|
||||
|
||||
/* AUDIO Class Config */
|
||||
#define USBD_AUDIO_FREQ 22100
|
||||
|
||||
/** @defgroup USBD_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Memory management macros */
|
||||
#define USBD_malloc malloc
|
||||
#define USBD_free free
|
||||
#define USBD_memset memset
|
||||
#define USBD_memcpy memcpy
|
||||
|
||||
/* DEBUG macros */
|
||||
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 0)
|
||||
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_UsrLog(...)
|
||||
#endif
|
||||
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 1)
|
||||
|
||||
#define USBD_ErrLog(...) printf("ERROR: ") ;\
|
||||
printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_ErrLog(...)
|
||||
#endif
|
||||
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 2)
|
||||
#define USBD_DbgLog(...) printf("DEBUG : ") ;\
|
||||
printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_DbgLog(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USBD_CONF_TEMPLATE_H */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
166
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_core.h
Normal file
166
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_core.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief Header file for usbd_core.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CORE_H
|
||||
#define __USBD_CORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usbd_ctlreq.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE
|
||||
* @brief This file is the Header file for usbd_core.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
#define USBD_SOF USBD_LL_SOF
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
|
||||
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
|
||||
|
||||
USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
|
||||
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
|
||||
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
|
||||
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
|
||||
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
|
||||
|
||||
/* USBD Low Level Driver */
|
||||
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev);
|
||||
USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t ep_type,
|
||||
uint16_t ep_mps);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr);
|
||||
USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t *pbuf,
|
||||
uint16_t size);
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint16_t size);
|
||||
|
||||
uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
|
||||
void USBD_LL_Delay (uint32_t Delay);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USBD_CORE_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
|
||||
113
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h
Normal file
113
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_req.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief Header file for the usbd_req.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_REQUEST_H
|
||||
#define __USB_REQUEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ
|
||||
* @brief header file for the usbd_req.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
|
||||
USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
|
||||
USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
|
||||
|
||||
|
||||
void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
|
||||
|
||||
void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata);
|
||||
|
||||
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_REQUEST_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
360
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_def.h
Normal file
360
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_def.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_def.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief General defines for the usb device library
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_DEF_H
|
||||
#define __USBD_DEF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USBD_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DEF
|
||||
* @brief general defines for the usb device library file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DEF_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
#define USB_LEN_DEV_QUALIFIER_DESC 0x0A
|
||||
#define USB_LEN_DEV_DESC 0x12
|
||||
#define USB_LEN_CFG_DESC 0x09
|
||||
#define USB_LEN_IF_DESC 0x09
|
||||
#define USB_LEN_EP_DESC 0x07
|
||||
#define USB_LEN_OTG_DESC 0x03
|
||||
#define USB_LEN_LANGID_STR_DESC 0x04
|
||||
#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09
|
||||
|
||||
#define USBD_IDX_LANGID_STR 0x00
|
||||
#define USBD_IDX_MFC_STR 0x01
|
||||
#define USBD_IDX_PRODUCT_STR 0x02
|
||||
#define USBD_IDX_SERIAL_STR 0x03
|
||||
#define USBD_IDX_CONFIG_STR 0x04
|
||||
#define USBD_IDX_INTERFACE_STR 0x05
|
||||
|
||||
#define USB_REQ_TYPE_STANDARD 0x00
|
||||
#define USB_REQ_TYPE_CLASS 0x20
|
||||
#define USB_REQ_TYPE_VENDOR 0x40
|
||||
#define USB_REQ_TYPE_MASK 0x60
|
||||
|
||||
#define USB_REQ_RECIPIENT_DEVICE 0x00
|
||||
#define USB_REQ_RECIPIENT_INTERFACE 0x01
|
||||
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
|
||||
#define USB_REQ_RECIPIENT_MASK 0x03
|
||||
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
#define USB_DESC_TYPE_DEVICE 1
|
||||
#define USB_DESC_TYPE_CONFIGURATION 2
|
||||
#define USB_DESC_TYPE_STRING 3
|
||||
#define USB_DESC_TYPE_INTERFACE 4
|
||||
#define USB_DESC_TYPE_ENDPOINT 5
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
|
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
|
||||
#define USB_DESC_TYPE_BOS 0x0F
|
||||
|
||||
#define USB_CONFIG_REMOTE_WAKEUP 2
|
||||
#define USB_CONFIG_SELF_POWERED 1
|
||||
|
||||
#define USB_FEATURE_EP_HALT 0
|
||||
#define USB_FEATURE_REMOTE_WAKEUP 1
|
||||
#define USB_FEATURE_TEST_MODE 2
|
||||
|
||||
#define USB_DEVICE_CAPABITY_TYPE 0x10
|
||||
|
||||
#define USB_HS_MAX_PACKET_SIZE 512
|
||||
#define USB_FS_MAX_PACKET_SIZE 64
|
||||
#define USB_MAX_EP0_SIZE 64
|
||||
|
||||
/* Device Status */
|
||||
#define USBD_STATE_DEFAULT 1
|
||||
#define USBD_STATE_ADDRESSED 2
|
||||
#define USBD_STATE_CONFIGURED 3
|
||||
#define USBD_STATE_SUSPENDED 4
|
||||
|
||||
|
||||
/* EP0 State */
|
||||
#define USBD_EP0_IDLE 0
|
||||
#define USBD_EP0_SETUP 1
|
||||
#define USBD_EP0_DATA_IN 2
|
||||
#define USBD_EP0_DATA_OUT 3
|
||||
#define USBD_EP0_STATUS_IN 4
|
||||
#define USBD_EP0_STATUS_OUT 5
|
||||
#define USBD_EP0_STALL 6
|
||||
|
||||
#define USBD_EP_TYPE_CTRL 0
|
||||
#define USBD_EP_TYPE_ISOC 1
|
||||
#define USBD_EP_TYPE_BULK 2
|
||||
#define USBD_EP_TYPE_INTR 3
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct usb_setup_req
|
||||
{
|
||||
|
||||
uint8_t bmRequest;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
}USBD_SetupReqTypedef;
|
||||
|
||||
struct _USBD_HandleTypeDef;
|
||||
|
||||
typedef uint8_t (*Init_t) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
|
||||
typedef uint8_t (*DeInit_t) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
|
||||
/* Control Endpoints*/
|
||||
typedef uint8_t (*Setup_t) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req);
|
||||
typedef uint8_t (*EP0_TxSent_t) (struct _USBD_HandleTypeDef *pdev );
|
||||
typedef uint8_t (*EP0_RxReady_t) (struct _USBD_HandleTypeDef *pdev );
|
||||
/* Class Specific Endpoints*/
|
||||
typedef uint8_t (*DataIn_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
|
||||
typedef uint8_t (*DataOut_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t* pData);
|
||||
typedef uint8_t (*SOF_t) (struct _USBD_HandleTypeDef *pdev);
|
||||
typedef uint8_t (*IsoINIncomplete_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
|
||||
typedef uint8_t (*IsoOUTIncomplete_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
|
||||
|
||||
typedef uint8_t *(*GetHSConfigDescriptor_t)(uint16_t *length);
|
||||
typedef uint8_t *(*GetFSConfigDescriptor_t)(uint16_t *length);
|
||||
typedef uint8_t *(*GetOtherSpeedConfigDescriptor_t)(uint16_t *length);
|
||||
typedef uint8_t *(*GetDeviceQualifierDescriptor_t)(uint16_t *length);
|
||||
#if (USBD_SUPPORT_USER_STRING == 1)
|
||||
typedef uint8_t *(*GetUsrStrDescriptor_t)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length);
|
||||
#endif
|
||||
|
||||
typedef struct _Device_cb
|
||||
{
|
||||
Init_t Init;
|
||||
DeInit_t DeInit;
|
||||
/* Control Endpoints*/
|
||||
Setup_t Setup;
|
||||
EP0_TxSent_t EP0_TxSent;
|
||||
EP0_RxReady_t EP0_RxReady;
|
||||
/* Class Specific Endpoints*/
|
||||
DataIn_t DataIn;
|
||||
DataOut_t DataOut;
|
||||
SOF_t SOF;
|
||||
IsoINIncomplete_t IsoINIncomplete;
|
||||
IsoOUTIncomplete_t IsoOUTIncomplete;
|
||||
|
||||
GetHSConfigDescriptor_t GetHSConfigDescriptor;
|
||||
GetFSConfigDescriptor_t GetFSConfigDescriptor;
|
||||
GetOtherSpeedConfigDescriptor_t GetOtherSpeedConfigDescriptor;
|
||||
GetDeviceQualifierDescriptor_t GetDeviceQualifierDescriptor;
|
||||
#if (USBD_SUPPORT_USER_STRING == 1)
|
||||
GetUsrStrDescriptor_t GetUsrStrDescriptor;
|
||||
#endif
|
||||
|
||||
} USBD_ClassTypeDef;
|
||||
|
||||
/* Following USB Device Speed */
|
||||
typedef enum
|
||||
{
|
||||
USBD_SPEED_HIGH = 0,
|
||||
USBD_SPEED_FULL = 1,
|
||||
USBD_SPEED_LOW = 2,
|
||||
}USBD_SpeedTypeDef;
|
||||
|
||||
/* Following USB Device status */
|
||||
typedef enum {
|
||||
USBD_OK = 0,
|
||||
USBD_BUSY,
|
||||
USBD_FAIL,
|
||||
}USBD_StatusTypeDef;
|
||||
|
||||
typedef uint8_t *(*GetDeviceDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetLangIDStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetManufacturerStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetProductStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetSerialStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetConfigurationStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetInterfaceStrDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
typedef uint8_t *(*GetBOSDescriptor_t)( USBD_SpeedTypeDef speed , uint16_t *length);
|
||||
|
||||
/* USB Device descriptors structure */
|
||||
typedef struct
|
||||
{
|
||||
GetDeviceDescriptor_t GetDeviceDescriptor;
|
||||
GetLangIDStrDescriptor_t GetLangIDStrDescriptor;
|
||||
GetManufacturerStrDescriptor_t GetManufacturerStrDescriptor;
|
||||
GetProductStrDescriptor_t GetProductStrDescriptor;
|
||||
GetSerialStrDescriptor_t GetSerialStrDescriptor;
|
||||
GetConfigurationStrDescriptor_t GetConfigurationStrDescriptor;
|
||||
GetInterfaceStrDescriptor_t GetInterfaceStrDescriptor;
|
||||
#if (USBD_LPM_ENABLED == 1)
|
||||
GetBOSDescriptor_t GetBOSDescriptor;
|
||||
#endif
|
||||
} USBD_DescriptorsTypeDef;
|
||||
|
||||
/* USB Device handle structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t status;
|
||||
uint32_t total_length;
|
||||
uint32_t rem_length;
|
||||
uint32_t maxpacket;
|
||||
} USBD_EndpointTypeDef;
|
||||
|
||||
/* USB Device handle structure */
|
||||
typedef struct _USBD_HandleTypeDef
|
||||
{
|
||||
uint8_t id;
|
||||
uint32_t dev_config;
|
||||
uint32_t dev_default_config;
|
||||
uint32_t dev_config_status;
|
||||
USBD_SpeedTypeDef dev_speed;
|
||||
USBD_EndpointTypeDef ep_in[15];
|
||||
USBD_EndpointTypeDef ep_out[15];
|
||||
uint32_t ep0_state;
|
||||
uint32_t ep0_data_len;
|
||||
uint8_t dev_state;
|
||||
uint8_t dev_old_state;
|
||||
uint8_t dev_address;
|
||||
uint8_t dev_connection_status;
|
||||
uint8_t dev_test_mode;
|
||||
uint32_t dev_remote_wakeup;
|
||||
|
||||
USBD_SetupReqTypedef request;
|
||||
USBD_DescriptorsTypeDef *pDesc;
|
||||
USBD_ClassTypeDef *pClass;
|
||||
void *pClassData;
|
||||
void *pUserData;
|
||||
void *pData;
|
||||
} USBD_HandleTypeDef;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
|
||||
(((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
|
||||
|
||||
#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
|
||||
#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
|
||||
#if defined ( __GNUC__ )
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif /* __weak */
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif /* __packed */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
||||
/* In HS mode and when the DMA is used, all variables and data structures dealing
|
||||
with the DMA during the transaction process should be 4-bytes aligned */
|
||||
|
||||
#if defined (__GNUC__) /* GNU Compiler */
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#define __ALIGN_BEGIN
|
||||
#else
|
||||
#define __ALIGN_END
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __ALIGN_BEGIN
|
||||
#elif defined (__TASKING__) /* TASKING Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#endif /* __CC_ARM */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USBD_DEF_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
128
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h
Normal file
128
src_usb/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_ioreq.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief Header file for the usbd_ioreq.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_IOREQ_H
|
||||
#define __USBD_IOREQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ
|
||||
* @brief header file for the usbd_ioreq.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *buf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev);
|
||||
|
||||
USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev);
|
||||
|
||||
uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev ,
|
||||
uint8_t epnum);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USBD_IOREQ_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_conf_template.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief USB Device configuration and interface file
|
||||
* This template should be copied to the user folder, renamed and customized
|
||||
* following user needs.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_core.h"
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initializes the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Opens an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param ep_type: Endpoint Type
|
||||
* @param ep_mps: Endpoint Max Packet Size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t ep_type,
|
||||
uint16_t ep_mps)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flushes an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Stall condition.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval Stall (1: Yes, 0: No)
|
||||
*/
|
||||
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a USB address to the device.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmits data over an endpoint.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param pbuf: Pointer to data to be sent
|
||||
* @param size: Data size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t *pbuf,
|
||||
uint16_t size)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares an endpoint for reception.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param pbuf: Pointer to data to be received
|
||||
* @param size: Data size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t *pbuf,
|
||||
uint16_t size)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the last transferred packet size.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval Recived Data Size
|
||||
*/
|
||||
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delays routine for the USB Device Library.
|
||||
* @param Delay: Delay in ms
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_LL_Delay(uint32_t Delay)
|
||||
{
|
||||
}
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
575
src_usb/STM32_USB_Device_Library/Core/Src/usbd_core.c
Normal file
575
src_usb/STM32_USB_Device_Library/Core/Src/usbd_core.c
Normal file
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_core.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief This file provides all the USBD core functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_core.h"
|
||||
|
||||
#include "os.h"
|
||||
/** @addtogroup STM32_USBD_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_Init
|
||||
* Initializes the device stack and load the class driver
|
||||
* @param pdev: device instance
|
||||
* @param pdesc: Descriptor structure address
|
||||
* @param id: Low level core index
|
||||
* @retval None
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id)
|
||||
{
|
||||
/* Check whether the USB Host handle is valid */
|
||||
if(pdev == NULL)
|
||||
{
|
||||
USBD_ErrLog("Invalid Device handle");
|
||||
return USBD_FAIL;
|
||||
}
|
||||
|
||||
memset(pdev, 0, sizeof(pdev));
|
||||
|
||||
/* Unlink previous class*/
|
||||
if(pdev->pClass != NULL)
|
||||
{
|
||||
pdev->pClass = NULL;
|
||||
}
|
||||
|
||||
/* Assign USBD Descriptors */
|
||||
if(pdesc != NULL)
|
||||
{
|
||||
pdev->pDesc = pdesc;
|
||||
}
|
||||
|
||||
/* Set Device initial State */
|
||||
pdev->dev_state = USBD_STATE_DEFAULT;
|
||||
pdev->id = id;
|
||||
/* Initialize low level driver */
|
||||
USBD_LL_Init(pdev);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DeInit
|
||||
* Re-Initialize th device library
|
||||
* @param pdev: device instance
|
||||
* @retval status: status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
/* Set Default State */
|
||||
pdev->dev_state = USBD_STATE_DEFAULT;
|
||||
|
||||
/* Free Class Resources */
|
||||
if(pdev->pClass != NULL) {
|
||||
((DeInit_t)PIC(pdev->pClass->DeInit))(pdev, pdev->dev_config);
|
||||
}
|
||||
|
||||
/* Stop the low level driver */
|
||||
USBD_LL_Stop(pdev);
|
||||
|
||||
/* Initialize low level driver */
|
||||
USBD_LL_DeInit(pdev);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_RegisterClass
|
||||
* Link class driver to Device Core.
|
||||
* @param pDevice : Device Handle
|
||||
* @param pclass: Class handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
|
||||
{
|
||||
USBD_StatusTypeDef status = USBD_OK;
|
||||
if(pclass != 0)
|
||||
{
|
||||
/* link the class to the USB Device handle */
|
||||
pdev->pClass = pclass;
|
||||
status = USBD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_ErrLog("Invalid Class handle");
|
||||
status = USBD_FAIL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Start
|
||||
* Start the USB Device Core.
|
||||
* @param pdev: Device Handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
|
||||
/* Start the low level driver */
|
||||
USBD_LL_Start(pdev);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Stop
|
||||
* Stop the USB Device Core.
|
||||
* @param pdev: Device Handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
/* Free Class Resources */
|
||||
if(pdev->pClass != NULL) {
|
||||
((DeInit_t)PIC(pdev->pClass->DeInit))(pdev, pdev->dev_config);
|
||||
}
|
||||
|
||||
/* Stop the low level driver */
|
||||
USBD_LL_Stop(pdev);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_RunTestMode
|
||||
* Launch test mode process
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_SetClassConfig
|
||||
* Configure device and start the interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: configuration index
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
USBD_StatusTypeDef ret = USBD_FAIL;
|
||||
|
||||
if(pdev->pClass != NULL)
|
||||
{
|
||||
/* Set configuration and Start the Class*/
|
||||
if(((Init_t)PIC(pdev->pClass->Init))(pdev, cfgidx) == 0)
|
||||
{
|
||||
ret = USBD_OK;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_ClrClassConfig
|
||||
* Clear current configuration
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: configuration index
|
||||
* @retval status: USBD_StatusTypeDef
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
/* Clear configuration and De-initialize the Class process*/
|
||||
if(pdev->pClass != NULL) {
|
||||
((DeInit_t)PIC(pdev->pClass->DeInit))(pdev, cfgidx);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_SetupStage
|
||||
* Handle the setup stage
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
|
||||
{
|
||||
|
||||
USBD_ParseSetupRequest(&pdev->request, psetup);
|
||||
|
||||
pdev->ep0_state = USBD_EP0_SETUP;
|
||||
pdev->ep0_data_len = pdev->request.wLength;
|
||||
|
||||
switch (pdev->request.bmRequest & 0x1F)
|
||||
{
|
||||
case USB_REQ_RECIPIENT_DEVICE:
|
||||
USBD_StdDevReq (pdev, &pdev->request);
|
||||
break;
|
||||
|
||||
case USB_REQ_RECIPIENT_INTERFACE:
|
||||
USBD_StdItfReq(pdev, &pdev->request);
|
||||
break;
|
||||
|
||||
case USB_REQ_RECIPIENT_ENDPOINT:
|
||||
USBD_StdEPReq(pdev, &pdev->request);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80);
|
||||
break;
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DataOutStage
|
||||
* Handle data OUT stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata)
|
||||
{
|
||||
USBD_EndpointTypeDef *pep;
|
||||
|
||||
if(epnum == 0)
|
||||
{
|
||||
pep = &pdev->ep_out[0];
|
||||
|
||||
if ( pdev->ep0_state == USBD_EP0_DATA_OUT)
|
||||
{
|
||||
if(pep->rem_length > pep->maxpacket)
|
||||
{
|
||||
pep->rem_length -= pep->maxpacket;
|
||||
|
||||
USBD_CtlContinueRx (pdev,
|
||||
pdata,
|
||||
MIN(pep->rem_length ,pep->maxpacket));
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pdev->pClass->EP0_RxReady != NULL)&&
|
||||
(pdev->dev_state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
((EP0_RxReady_t)PIC(pdev->pClass->EP0_RxReady))(pdev);
|
||||
}
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((pdev->pClass->DataOut != NULL)&&
|
||||
(pdev->dev_state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
((DataOut_t)PIC(pdev->pClass->DataOut))(pdev, epnum, pdata);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DataInStage
|
||||
* Handle data in stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata)
|
||||
{
|
||||
USBD_EndpointTypeDef *pep;
|
||||
|
||||
if(epnum == 0)
|
||||
{
|
||||
pep = &pdev->ep_in[0];
|
||||
|
||||
if ( pdev->ep0_state == USBD_EP0_DATA_IN)
|
||||
{
|
||||
if(pep->rem_length > pep->maxpacket)
|
||||
{
|
||||
pep->rem_length -= pep->maxpacket;
|
||||
|
||||
USBD_CtlContinueSendData (pdev,
|
||||
pdata,
|
||||
pep->rem_length);
|
||||
|
||||
/* Prepare endpoint for premature end of transfer */
|
||||
USBD_LL_PrepareReceive (pdev,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{ /* last packet is MPS multiple, so send ZLP packet */
|
||||
if((pep->total_length % pep->maxpacket == 0) &&
|
||||
(pep->total_length >= pep->maxpacket) &&
|
||||
(pep->total_length < pdev->ep0_data_len ))
|
||||
{
|
||||
|
||||
USBD_CtlContinueSendData(pdev , NULL, 0);
|
||||
pdev->ep0_data_len = 0;
|
||||
|
||||
/* Prepare endpoint for premature end of transfer */
|
||||
USBD_LL_PrepareReceive (pdev,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pdev->pClass != NULL && (pdev->pClass->EP0_TxSent != NULL)&&
|
||||
(pdev->dev_state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
((EP0_TxSent_t)PIC(pdev->pClass->EP0_TxSent))(pdev);
|
||||
}
|
||||
USBD_CtlReceiveStatus(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pdev->dev_test_mode == 1)
|
||||
{
|
||||
USBD_RunTestMode(pdev);
|
||||
pdev->dev_test_mode = 0;
|
||||
}
|
||||
}
|
||||
else if(pdev->pClass != NULL && (pdev->pClass->DataIn != NULL)&&
|
||||
(pdev->dev_state == USBD_STATE_CONFIGURED))
|
||||
{
|
||||
((DataIn_t)PIC(pdev->pClass->DataIn))(pdev, epnum);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_LL_Reset
|
||||
* Handle Reset event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
#if 0 // fastpath, done on the L4 for MOAR SPEED
|
||||
/* Open EP0 OUT */
|
||||
USBD_LL_OpenEP(pdev,
|
||||
0x00,
|
||||
USBD_EP_TYPE_CTRL,
|
||||
USB_MAX_EP0_SIZE);
|
||||
|
||||
/* Open EP0 IN */
|
||||
USBD_LL_OpenEP(pdev,
|
||||
0x80,
|
||||
USBD_EP_TYPE_CTRL,
|
||||
USB_MAX_EP0_SIZE);
|
||||
#endif // 0
|
||||
pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
|
||||
|
||||
|
||||
pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
|
||||
/* Upon Reset call user call back */
|
||||
pdev->dev_state = USBD_STATE_DEFAULT;
|
||||
|
||||
if (pdev->pClass) {
|
||||
((DeInit_t)PIC(pdev->pClass->DeInit))(pdev, pdev->dev_config);
|
||||
}
|
||||
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_LL_Reset
|
||||
* Handle Reset event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed)
|
||||
{
|
||||
pdev->dev_speed = speed;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Suspend
|
||||
* Handle Suspend event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
pdev->dev_old_state = pdev->dev_state;
|
||||
pdev->dev_state = USBD_STATE_SUSPENDED;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Resume
|
||||
* Handle Resume event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
pdev->dev_state = pdev->dev_old_state;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_SOF
|
||||
* Handle SOF event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
if(pdev->dev_state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
if(pdev->pClass->SOF != NULL)
|
||||
{
|
||||
((SOF_t)PIC(pdev->pClass->SOF))(pdev);
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_IsoINIncomplete
|
||||
* Handle iso in incomplete event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_IsoOUTIncomplete
|
||||
* Handle iso out incomplete event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DevConnected
|
||||
* Handle device connection event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DevDisconnected
|
||||
* Handle device disconnection event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
/* Free Class Resources */
|
||||
pdev->dev_state = USBD_STATE_DEFAULT;
|
||||
// done upon reset // ((DeInit_t)PIC(pdev->pClass->DeInit))(pdev, pdev->dev_config);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
787
src_usb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
Normal file
787
src_usb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
Normal file
@@ -0,0 +1,787 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_req.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief This file provides the standard USB requests following chapter 9.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_ctlreq.h"
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ
|
||||
* @brief USB standard requests module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static uint8_t USBD_GetLen(uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_StdDevReq
|
||||
* Handle standard usb device requests
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
|
||||
{
|
||||
USBD_StatusTypeDef ret = USBD_OK;
|
||||
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
|
||||
USBD_GetDescriptor (pdev, req) ;
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
USBD_SetAddress(pdev, req);
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
USBD_SetConfig (pdev , req);
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_CONFIGURATION:
|
||||
USBD_GetConfig (pdev , req);
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS:
|
||||
USBD_GetStatus (pdev , req);
|
||||
break;
|
||||
|
||||
|
||||
case USB_REQ_SET_FEATURE:
|
||||
USBD_SetFeature (pdev , req);
|
||||
break;
|
||||
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
USBD_ClrFeature (pdev , req);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_StdItfReq
|
||||
* Handle standard usb interface requests
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
|
||||
{
|
||||
USBD_StatusTypeDef ret = USBD_OK;
|
||||
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_CONFIGURED:
|
||||
|
||||
if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
|
||||
{
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
|
||||
if((req->wLength == 0)&& (ret == USBD_OK))
|
||||
{
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_StdEPReq
|
||||
* Handle standard usb endpoint requests
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
|
||||
{
|
||||
|
||||
uint8_t ep_addr;
|
||||
USBD_StatusTypeDef ret = USBD_OK;
|
||||
USBD_EndpointTypeDef *pep;
|
||||
ep_addr = LOBYTE(req->wIndex);
|
||||
|
||||
/* Check if it is a class request */
|
||||
if ((req->bmRequest & 0x60) == 0x20)
|
||||
{
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
switch (req->bRequest)
|
||||
{
|
||||
|
||||
case USB_REQ_SET_FEATURE :
|
||||
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
if ((ep_addr != 0x00) && (ep_addr != 0x80))
|
||||
{
|
||||
USBD_LL_StallEP(pdev , ep_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case USBD_STATE_CONFIGURED:
|
||||
if (req->wValue == USB_FEATURE_EP_HALT)
|
||||
{
|
||||
if ((ep_addr != 0x00) && (ep_addr != 0x80))
|
||||
{
|
||||
USBD_LL_StallEP(pdev , ep_addr);
|
||||
|
||||
}
|
||||
}
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
USBD_CtlSendStatus(pdev);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_CLEAR_FEATURE :
|
||||
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
if ((ep_addr != 0x00) && (ep_addr != 0x80))
|
||||
{
|
||||
USBD_LL_StallEP(pdev , ep_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case USBD_STATE_CONFIGURED:
|
||||
if (req->wValue == USB_FEATURE_EP_HALT)
|
||||
{
|
||||
if ((ep_addr & 0x7F) != 0x00)
|
||||
{
|
||||
USBD_LL_ClearStallEP(pdev , ep_addr);
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
}
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS:
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
if ((ep_addr & 0x7F) != 0x00)
|
||||
{
|
||||
USBD_LL_StallEP(pdev , ep_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case USBD_STATE_CONFIGURED:
|
||||
pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\
|
||||
&pdev->ep_out[ep_addr & 0x7F];
|
||||
if(USBD_LL_IsStallEP(pdev, ep_addr))
|
||||
{
|
||||
pep->status = 0x0001;
|
||||
}
|
||||
else
|
||||
{
|
||||
pep->status = 0x0000;
|
||||
}
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&pep->status,
|
||||
2);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief USBD_GetDescriptor
|
||||
* Handle Get Descriptor requests
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t *pbuf;
|
||||
|
||||
|
||||
switch (req->wValue >> 8)
|
||||
{
|
||||
#if (USBD_LPM_ENABLED == 1)
|
||||
case USB_DESC_TYPE_BOS:
|
||||
pbuf = ((GetBOSDescriptor_t)PIC(pdev->pDesc->GetBOSDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
#endif
|
||||
case USB_DESC_TYPE_DEVICE:
|
||||
pbuf = ((GetDeviceDescriptor_t)PIC(pdev->pDesc->GetDeviceDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_CONFIGURATION:
|
||||
if(pdev->dev_speed == USBD_SPEED_HIGH )
|
||||
{
|
||||
pbuf = (uint8_t *)((GetHSConfigDescriptor_t)PIC(pdev->pClass->GetHSConfigDescriptor))(&len);
|
||||
//pbuf[1] = USB_DESC_TYPE_CONFIGURATION; CONST BUFFER KTHX
|
||||
}
|
||||
else
|
||||
{
|
||||
pbuf = (uint8_t *)((GetFSConfigDescriptor_t)PIC(pdev->pClass->GetFSConfigDescriptor))(&len);
|
||||
//pbuf[1] = USB_DESC_TYPE_CONFIGURATION; CONST BUFFER KTHX
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_STRING:
|
||||
switch ((uint8_t)(req->wValue))
|
||||
{
|
||||
case USBD_IDX_LANGID_STR:
|
||||
pbuf = ((GetLangIDStrDescriptor_t)PIC(pdev->pDesc->GetLangIDStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USBD_IDX_MFC_STR:
|
||||
pbuf = ((GetManufacturerStrDescriptor_t)PIC(pdev->pDesc->GetManufacturerStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USBD_IDX_PRODUCT_STR:
|
||||
pbuf = ((GetProductStrDescriptor_t)PIC(pdev->pDesc->GetProductStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USBD_IDX_SERIAL_STR:
|
||||
pbuf = ((GetSerialStrDescriptor_t)PIC(pdev->pDesc->GetSerialStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USBD_IDX_CONFIG_STR:
|
||||
pbuf = ((GetConfigurationStrDescriptor_t)PIC(pdev->pDesc->GetConfigurationStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
case USBD_IDX_INTERFACE_STR:
|
||||
pbuf = ((GetInterfaceStrDescriptor_t)PIC(pdev->pDesc->GetInterfaceStrDescriptor))(pdev->dev_speed, &len);
|
||||
break;
|
||||
|
||||
default:
|
||||
#if (USBD_SUPPORT_USER_STRING == 1)
|
||||
pbuf = ((GetUsrStrDescriptor_t)PIC(pdev->pClass->GetUsrStrDescriptor))(pdev, (req->wValue) , &len);
|
||||
break;
|
||||
#else
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case USB_DESC_TYPE_DEVICE_QUALIFIER:
|
||||
|
||||
if(pdev->dev_speed == USBD_SPEED_HIGH )
|
||||
{
|
||||
pbuf = (uint8_t *)((GetDeviceQualifierDescriptor_t)PIC(pdev->pClass->GetDeviceQualifierDescriptor))(&len);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
}
|
||||
|
||||
case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
|
||||
if(pdev->dev_speed == USBD_SPEED_HIGH )
|
||||
{
|
||||
pbuf = (uint8_t *)((GetOtherSpeedConfigDescriptor_t)PIC(pdev->pClass->GetOtherSpeedConfigDescriptor))(&len);
|
||||
// pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; CONST BUFFER KTHX
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
}
|
||||
|
||||
if((len != 0)&& (req->wLength != 0))
|
||||
{
|
||||
|
||||
len = MIN(len , req->wLength);
|
||||
|
||||
// prepare abort if host does not read the whole data
|
||||
USBD_CtlReceiveStatus(pdev);
|
||||
|
||||
// start transfer
|
||||
USBD_CtlSendData (pdev,
|
||||
pbuf,
|
||||
len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_SetAddress
|
||||
* Set device address
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
uint8_t dev_addr;
|
||||
|
||||
if ((req->wIndex == 0) && (req->wLength == 0))
|
||||
{
|
||||
dev_addr = (uint8_t)(req->wValue) & 0x7F;
|
||||
|
||||
if (pdev->dev_state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
}
|
||||
else
|
||||
{
|
||||
pdev->dev_address = dev_addr;
|
||||
USBD_LL_SetUSBAddress(pdev, dev_addr);
|
||||
USBD_CtlSendStatus(pdev);
|
||||
|
||||
if (dev_addr != 0)
|
||||
{
|
||||
pdev->dev_state = USBD_STATE_ADDRESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdev->dev_state = USBD_STATE_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_SetConfig
|
||||
* Handle Set device configuration request
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
|
||||
static uint8_t cfgidx;
|
||||
|
||||
cfgidx = (uint8_t)(req->wValue);
|
||||
|
||||
if (cfgidx > USBD_MAX_NUM_CONFIGURATION )
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
if (cfgidx)
|
||||
{
|
||||
pdev->dev_config = cfgidx;
|
||||
pdev->dev_state = USBD_STATE_CONFIGURED;
|
||||
if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
}
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
break;
|
||||
|
||||
case USBD_STATE_CONFIGURED:
|
||||
if (cfgidx == 0)
|
||||
{
|
||||
pdev->dev_state = USBD_STATE_ADDRESSED;
|
||||
pdev->dev_config = cfgidx;
|
||||
USBD_ClrClassConfig(pdev , cfgidx);
|
||||
USBD_CtlSendStatus(pdev);
|
||||
|
||||
}
|
||||
else if (cfgidx != pdev->dev_config)
|
||||
{
|
||||
/* Clear old configuration */
|
||||
USBD_ClrClassConfig(pdev , pdev->dev_config);
|
||||
|
||||
/* set new configuration */
|
||||
pdev->dev_config = cfgidx;
|
||||
if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
return;
|
||||
}
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_GetConfig
|
||||
* Handle Get device configuration request
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
|
||||
if (req->wLength != 1)
|
||||
{
|
||||
USBD_CtlError(pdev , req);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pdev->dev_state )
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
pdev->dev_default_config = 0;
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&pdev->dev_default_config,
|
||||
1);
|
||||
break;
|
||||
|
||||
case USBD_STATE_CONFIGURED:
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&pdev->dev_config,
|
||||
1);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_GetStatus
|
||||
* Handle Get Status request
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
|
||||
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
case USBD_STATE_CONFIGURED:
|
||||
|
||||
#if ( USBD_SELF_POWERED == 1)
|
||||
pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
|
||||
#else
|
||||
pdev->dev_config_status = 0;
|
||||
#endif
|
||||
|
||||
if (pdev->dev_remote_wakeup)
|
||||
{
|
||||
pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
|
||||
}
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)& pdev->dev_config_status,
|
||||
2);
|
||||
break;
|
||||
|
||||
default :
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_SetFeature
|
||||
* Handle Set device feature request
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
|
||||
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
|
||||
{
|
||||
pdev->dev_remote_wakeup = 1;
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_ClrFeature
|
||||
* Handle clear device feature request
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval status
|
||||
*/
|
||||
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
switch (pdev->dev_state)
|
||||
{
|
||||
case USBD_STATE_ADDRESSED:
|
||||
case USBD_STATE_CONFIGURED:
|
||||
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
|
||||
{
|
||||
pdev->dev_remote_wakeup = 0;
|
||||
((Setup_t)PIC(pdev->pClass->Setup)) (pdev, req);
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
USBD_CtlError(pdev , req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_ParseSetupRequest
|
||||
* Copy buffer into setup structure
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
|
||||
{
|
||||
req->bmRequest = *(uint8_t *) (pdata);
|
||||
req->bRequest = *(uint8_t *) (pdata + 1);
|
||||
req->wValue = SWAPBYTE (pdata + 2);
|
||||
req->wIndex = SWAPBYTE (pdata + 4);
|
||||
req->wLength = SWAPBYTE (pdata + 6);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlError
|
||||
* Handle USB low level Error
|
||||
* @param pdev: device instance
|
||||
* @param req: usb request
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void USBD_CtlError( USBD_HandleTypeDef *pdev ,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
USBD_LL_StallEP(pdev , 0x80);
|
||||
USBD_LL_StallEP(pdev , 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_GetString
|
||||
* Convert Ascii string into unicode one
|
||||
* @param desc : descriptor buffer
|
||||
* @param unicode : Formatted string buffer (unicode)
|
||||
* @param len : descriptor length
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
|
||||
if (desc != NULL)
|
||||
{
|
||||
*len = USBD_GetLen(desc) * 2 + 2;
|
||||
unicode[idx++] = *len;
|
||||
unicode[idx++] = USB_DESC_TYPE_STRING;
|
||||
|
||||
while (*desc != '\0')
|
||||
{
|
||||
unicode[idx++] = *desc++;
|
||||
unicode[idx++] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_GetLen
|
||||
* return the string length
|
||||
* @param buf : pointer to the ascii string buffer
|
||||
* @retval string length
|
||||
*/
|
||||
static uint8_t USBD_GetLen(uint8_t *buf)
|
||||
{
|
||||
uint8_t len = 0;
|
||||
|
||||
while (*buf != '\0')
|
||||
{
|
||||
len++;
|
||||
buf++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
233
src_usb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
Normal file
233
src_usb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_ioreq.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.4.1
|
||||
* @date 19-June-2015
|
||||
* @brief This file provides the IO requests APIs for control endpoints.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ
|
||||
* @brief control I/O requests module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlSendData
|
||||
* send data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be sent
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
/* Set EP0 State */
|
||||
pdev->ep0_state = USBD_EP0_DATA_IN;
|
||||
pdev->ep_in[0].total_length = len;
|
||||
pdev->ep_in[0].rem_length = len;
|
||||
/* Start the transfer */
|
||||
USBD_LL_Transmit (pdev, 0x00, pbuf, len);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlContinueSendData
|
||||
* continue sending data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be sent
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
/* Start the next transfer */
|
||||
USBD_LL_Transmit (pdev, 0x00, pbuf, len);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlPrepareRx
|
||||
* receive data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be received
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
/* Set EP0 State */
|
||||
pdev->ep0_state = USBD_EP0_DATA_OUT;
|
||||
pdev->ep_out[0].total_length = len;
|
||||
pdev->ep_out[0].rem_length = len;
|
||||
/* Start the transfer */
|
||||
USBD_LL_PrepareReceive (pdev,
|
||||
0,
|
||||
len);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlContinueRx
|
||||
* continue receive data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be received
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
|
||||
USBD_LL_PrepareReceive (pdev,
|
||||
0,
|
||||
len);
|
||||
return USBD_OK;
|
||||
}
|
||||
/**
|
||||
* @brief USBD_CtlSendStatus
|
||||
* send zero lzngth packet on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
|
||||
/* Set EP0 State */
|
||||
pdev->ep0_state = USBD_EP0_STATUS_IN;
|
||||
|
||||
/* Start the transfer */
|
||||
USBD_LL_Transmit (pdev, 0x00, NULL, 0);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlReceiveStatus
|
||||
* receive zero lzngth packet on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
/* Set EP0 State */
|
||||
pdev->ep0_state = USBD_EP0_STATUS_OUT;
|
||||
|
||||
/* Start the transfer */
|
||||
USBD_LL_PrepareReceive ( pdev,
|
||||
0,
|
||||
0);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_GetRxCount
|
||||
* returns the received data length
|
||||
* @param pdev: device instance
|
||||
* @param ep_addr: endpoint address
|
||||
* @retval Rx Data blength
|
||||
*/
|
||||
uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr)
|
||||
{
|
||||
return USBD_LL_GetRxDataSize(pdev, ep_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
1219
src_usb/STM32_USB_Device_Library/Release_Notes.html
Normal file
1219
src_usb/STM32_USB_Device_Library/Release_Notes.html
Normal file
File diff suppressed because it is too large
Load Diff
596
src_usb/usbd_conf.c
Normal file
596
src_usb/usbd_conf.c
Normal file
@@ -0,0 +1,596 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : usbd_conf.c
|
||||
* @brief : This file implements the board support package for the USB device 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
#include "os_io_seproxyhal.h"
|
||||
//#include "usbd_hid.h"
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
/* USER CODE END 0 */
|
||||
/* Exported function prototypes -----------------------------------------------*/
|
||||
extern USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev);
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
//void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state);
|
||||
|
||||
/*******************************************************************************
|
||||
LL Driver Callbacks (PCD USB Device Library)
|
||||
*******************************************************************************/
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Setup Stage callback
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
|
||||
USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data Out Stage callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @param epnum: Endpoint Number
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data In Stage callback..
|
||||
* @param hpcd: PCD handle
|
||||
* @param epnum: Endpoint Number
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SOF callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_SOF(hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
|
||||
|
||||
/*Set USB Current Speed*/
|
||||
switch (hpcd->Init.speed)
|
||||
{
|
||||
case PCD_SPEED_FULL:
|
||||
speed = USBD_SPEED_FULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
speed = USBD_SPEED_FULL;
|
||||
break;
|
||||
}
|
||||
USBD_LL_SetSpeed(hpcd->pData, speed);
|
||||
|
||||
/*Reset Device*/
|
||||
USBD_LL_Reset(hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend callback.
|
||||
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_Suspend(hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume callback.
|
||||
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_Resume(hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ISOOUTIncomplete callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @param epnum: Endpoint Number
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ISOINIncomplete callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @param epnum: Endpoint Number
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
USBD_LL_IsoINIncomplete(hpcd->pData, epnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ConnectCallback callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_DevConnected(hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnect callback.
|
||||
* @param hpcd: PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_DevDisconnected(hpcd->pData);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
LL Driver Interface (USB Device Library --> PCD)
|
||||
*******************************************************************************/
|
||||
unsigned int ep_in_stall;
|
||||
unsigned int ep_out_stall;
|
||||
/**
|
||||
* @brief Initializes the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
ep_in_stall = 0;
|
||||
ep_out_stall = 0;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
uint8_t buffer[5];
|
||||
|
||||
// reset address
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 2;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_ADDR;
|
||||
buffer[4] = 0;
|
||||
io_seproxyhal_spi_send(buffer, 5);
|
||||
|
||||
// start usb operation
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 1;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_CONNECT;
|
||||
io_seproxyhal_spi_send(buffer, 4);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the Low Level portion of the Device driver.
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 1;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT;
|
||||
io_seproxyhal_spi_send(buffer, 4);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Opens an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param ep_type: Endpoint Type
|
||||
* @param ep_mps: Endpoint Max Packet Size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t ep_type,
|
||||
uint16_t ep_mps)
|
||||
{
|
||||
uint8_t buffer[8];
|
||||
|
||||
ep_in_stall = 0;
|
||||
ep_out_stall = 0;
|
||||
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 5;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_ENDPOINTS;
|
||||
buffer[4] = 1;
|
||||
buffer[5] = ep_addr;
|
||||
buffer[6] = 0;
|
||||
switch(ep_type) {
|
||||
case USBD_EP_TYPE_CTRL:
|
||||
buffer[6] = SEPROXYHAL_TAG_USB_CONFIG_TYPE_CONTROL;
|
||||
break;
|
||||
case USBD_EP_TYPE_ISOC:
|
||||
buffer[6] = SEPROXYHAL_TAG_USB_CONFIG_TYPE_ISOCHRONOUS;
|
||||
break;
|
||||
case USBD_EP_TYPE_BULK:
|
||||
buffer[6] = SEPROXYHAL_TAG_USB_CONFIG_TYPE_BULK;
|
||||
break;
|
||||
case USBD_EP_TYPE_INTR:
|
||||
buffer[6] = SEPROXYHAL_TAG_USB_CONFIG_TYPE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
buffer[7] = ep_mps;
|
||||
io_seproxyhal_spi_send(buffer, 8);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t buffer[8];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 5;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_ENDPOINTS;
|
||||
buffer[4] = 1;
|
||||
buffer[5] = ep_addr;
|
||||
buffer[6] = SEPROXYHAL_TAG_USB_CONFIG_TYPE_DISABLED;
|
||||
buffer[7] = 0;
|
||||
io_seproxyhal_spi_send(buffer, 8);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flushes an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
//HAL_PCD_EP_Flush(pdev->pData, ep_addr);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 3;
|
||||
buffer[3] = ep_addr;
|
||||
buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_STALL;
|
||||
buffer[5] = 0;
|
||||
io_seproxyhal_spi_send(buffer, 6);
|
||||
if (ep_addr & 0x80) {
|
||||
ep_in_stall |= (1<<(ep_addr&0x7F));
|
||||
}
|
||||
else {
|
||||
ep_out_stall |= (1<<(ep_addr&0x7F));
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 3;
|
||||
buffer[3] = ep_addr;
|
||||
buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_UNSTALL;
|
||||
buffer[5] = 0;
|
||||
io_seproxyhal_spi_send(buffer, 6);
|
||||
if (ep_addr & 0x80) {
|
||||
ep_in_stall &= ~(1<<(ep_addr&0x7F));
|
||||
}
|
||||
else {
|
||||
ep_out_stall &= ~(1<<(ep_addr&0x7F));
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Stall condition.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval Stall (1: Yes, 0: No)
|
||||
*/
|
||||
uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
if((ep_addr & 0x80) == 0x80)
|
||||
{
|
||||
return ep_in_stall & (1<<(ep_addr&0x7F));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ep_out_stall & (1<<(ep_addr&0x7F));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Assigns a USB address to the device.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr)
|
||||
{
|
||||
uint8_t buffer[5];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_CONFIG;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 2;
|
||||
buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_ADDR;
|
||||
buffer[4] = dev_addr;
|
||||
io_seproxyhal_spi_send(buffer, 5);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmits data over an endpoint.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param pbuf: Pointer to data to be sent
|
||||
* @param size: Data size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint8_t *pbuf,
|
||||
uint16_t size)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||
buffer[1] = (3+size)>>8;
|
||||
buffer[2] = (3+size);
|
||||
buffer[3] = ep_addr;
|
||||
buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
||||
buffer[5] = size;
|
||||
io_seproxyhal_spi_send(buffer, 6);
|
||||
io_seproxyhal_spi_send(pbuf, size);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares an endpoint for reception.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @param pbuf: Pointer to data to be received
|
||||
* @param size: Data size
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_addr,
|
||||
uint16_t size)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||
buffer[1] = (3/*+size*/)>>8;
|
||||
buffer[2] = (3/*+size*/);
|
||||
buffer[3] = ep_addr;
|
||||
buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_OUT;
|
||||
buffer[5] = size;
|
||||
io_seproxyhal_spi_send(buffer, 6);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief GPIO EXTI Callback function
|
||||
* Handle USB VBUS detection upon External interrupt
|
||||
* @param GPIO_Pin
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
|
||||
{
|
||||
if (GPIO_Pin == GPIO_PIN_9)
|
||||
{
|
||||
HAL_PCDEx_BCD_VBUSDetect (&hpcd_USB_OTG_FS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the last transfered packet size.
|
||||
* @param pdev: Device handle
|
||||
* @param ep_addr: Endpoint Number
|
||||
* @retval Recived Data Size
|
||||
*/
|
||||
uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
|
||||
{
|
||||
// unused
|
||||
return 0; //HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delays routine for the USB Device Library.
|
||||
* @param Delay: Delay in ms
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_LL_Delay (uint32_t Delay)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
#endif //0
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Software Device Connection
|
||||
* @param hpcd: PCD handle
|
||||
* @param state: connection state (0 : disconnected / 1: connected)
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
if (state == 1)
|
||||
{
|
||||
/* Configure Low Connection State */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure High Connection State */
|
||||
|
||||
}
|
||||
/* USER CODE END 6 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify if the Battery Charging Detection mode (BCD) is used :
|
||||
* return USBD_OK if true
|
||||
* else return USBD_FAIL if false
|
||||
* @param pdev: Device handle
|
||||
* @retval USBD Status
|
||||
*/
|
||||
USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_FAIL;
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
|
||||
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
#include "os_io_seproxyhal.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_customhid.h"
|
||||
// the USB device
|
||||
USBD_HandleTypeDef USBD_Device;
|
||||
|
||||
// endpoints transport length
|
||||
volatile unsigned char G_io_usb_ep_xfer_len[IO_USB_MAX_ENDPOINTS];
|
||||
|
||||
// interaction variable with io seproxyhal to get the total length transferred when all RX packets have been processed.
|
||||
extern volatile unsigned short G_io_apdu_length;
|
||||
int8_t CUSTOM_HID_OutEvent (uint8_t* hid_report)
|
||||
{
|
||||
if (hid_report) {
|
||||
// add to the hid transport
|
||||
switch(io_usb_hid_receive(io_usb_send_apdu_data, hid_report, G_io_usb_ep_xfer_len[2])) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case IO_USB_APDU_RECEIVED:
|
||||
G_io_apdu_length = G_io_usb_hid_total_length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void io_usb_enable(unsigned char enabled) {
|
||||
if (enabled) {
|
||||
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
||||
/* Init Device Library */
|
||||
USBD_Init(&USBD_Device, &HID_Desc, 0);
|
||||
|
||||
/* Register the HID class */
|
||||
USBD_RegisterClass(&USBD_Device, &USBD_CUSTOM_HID);
|
||||
|
||||
USBD_CUSTOM_HID_RegisterInterface(&USBD_Device, &USBD_CustomHID_template_fops);
|
||||
|
||||
/* Start Device Process */
|
||||
USBD_Start(&USBD_Device);
|
||||
}
|
||||
else {
|
||||
USBD_DeInit(&USBD_Device);
|
||||
}
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
177
src_usb/usbd_conf.h
Normal file
177
src_usb/usbd_conf.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : usbd_conf.h
|
||||
* @brief : Header for usbd_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 __USBD_CONF__H__
|
||||
#define __USBD_CONF__H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
|
||||
/** @addtogroup USBD_OTG_DRIVER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF
|
||||
* @brief usb otg low level driver configuration file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_NUM_INTERFACES 1
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_NUM_CONFIGURATION 1
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_STR_DESC_SIZ 512
|
||||
/*---------- -----------*/
|
||||
#define USBD_SUPPORT_USER_STRING 0
|
||||
/*---------- -----------*/
|
||||
#define USBD_DEBUG_LEVEL 0
|
||||
/*---------- -----------*/
|
||||
#define USBD_LPM_ENABLED 1
|
||||
/*---------- -----------*/
|
||||
#define USBD_SELF_POWERED 1
|
||||
|
||||
/****************************************/
|
||||
/* #define for FS and HS identification */
|
||||
#define DEVICE_FS 0
|
||||
|
||||
/** @defgroup USBD_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Memory management macros */
|
||||
#define USBD_malloc (uint32_t *)USBD_static_malloc
|
||||
#define USBD_free USBD_static_free
|
||||
#define USBD_memset /* Not used */
|
||||
#define USBD_memcpy /* Not used */
|
||||
|
||||
#define USBD_Delay HAL_Delay
|
||||
|
||||
/* DEBUG macros */
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 0)
|
||||
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_UsrLog(...)
|
||||
#endif
|
||||
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 1)
|
||||
|
||||
#define USBD_ErrLog(...) printf("ERROR: ") ;\
|
||||
printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_ErrLog(...)
|
||||
#endif
|
||||
|
||||
|
||||
#if (USBD_DEBUG_LEVEL > 2)
|
||||
#define USBD_DbgLog(...) printf("DEBUG : ") ;\
|
||||
printf(__VA_ARGS__);\
|
||||
printf("\n");
|
||||
#else
|
||||
#define USBD_DbgLog(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CONF_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void *USBD_static_malloc(uint32_t size);
|
||||
void USBD_static_free(void *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__USBD_CONF__H__
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
78
src_usb/usbd_customhid_if_template.c
Normal file
78
src_usb/usbd_customhid_if_template.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_customhid_if_template.c
|
||||
* @author MCD Application Team
|
||||
* @version V2.2.0
|
||||
* @date 13-June-2014
|
||||
* @brief USB Device Custom HID interface file.
|
||||
* This template should be copied to the user folder, renamed and customized
|
||||
* following user needs.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_customhid_if_template.h"
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
static int8_t CUSTOM_HID_Init (void);
|
||||
static int8_t CUSTOM_HID_DeInit (void);
|
||||
int8_t CUSTOM_HID_OutEvent (uint8_t* hid_report);
|
||||
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
USBD_CUSTOM_HID_ItfTypeDef const USBD_CustomHID_template_fops =
|
||||
{
|
||||
CUSTOM_HID_Init,
|
||||
CUSTOM_HID_DeInit,
|
||||
CUSTOM_HID_OutEvent,
|
||||
};
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief TEMPLATE_CUSTOM_HID_Init
|
||||
* Initializes the CUSTOM HID media low layer
|
||||
* @param None
|
||||
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CUSTOM_HID_Init(void)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TEMPLATE_CUSTOM_HID_DeInit
|
||||
* DeInitializes the CUSTOM HID media low layer
|
||||
* @param None
|
||||
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CUSTOM_HID_DeInit(void)
|
||||
{
|
||||
/*
|
||||
Add your deinitialization code here
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
49
src_usb/usbd_customhid_if_template.h
Normal file
49
src_usb/usbd_customhid_if_template.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_customhid_if_template.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.2.0
|
||||
* @date 13-June-2014
|
||||
* @brief Header for usbd_customhid_if_template.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for th?
|
||||
e specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CUSTOM_HID_IF_TEMPLATE_H
|
||||
#define __USBD_CUSTOM_HID_IF_TEMPLATE_H
|
||||
|
||||
#define USBD_CUSTOMHID_REPORT_DESC_SIZE 0x22
|
||||
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x40
|
||||
|
||||
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 0x22
|
||||
#define USBD_CUSTOM_HID_OUTREPORT_BUF_SIZE 0x40
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_customhid.h"
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
extern USBD_CUSTOM_HID_ItfTypeDef const USBD_CustomHID_template_fops;
|
||||
|
||||
#endif /* __USBD_CUSTOM_HID_IF_TEMPLATE_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
29
src_usb/usbd_desc.c
Normal file
29
src_usb/usbd_desc.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_desc.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.1
|
||||
* @date 18-June-2014
|
||||
* @brief This file provides the USBD descriptors and string formating method.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
48
src_usb/usbd_desc.h
Normal file
48
src_usb/usbd_desc.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_desc.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.1
|
||||
* @date 18-June-2014
|
||||
* @brief Header for usbd_desc.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_DESC_H
|
||||
#define __USBD_DESC_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define DEVICE_ID1 (0x1FF80050)
|
||||
#define DEVICE_ID2 (0x1FF80054)
|
||||
#define DEVICE_ID3 (0x1FF80064)
|
||||
|
||||
#define USB_SIZ_STRING_SERIAL 0x1A
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
extern const USBD_DescriptorsTypeDef HID_Desc;
|
||||
|
||||
#endif /* __USBD_DESC_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
Reference in New Issue
Block a user