diff --git a/hardware/arduino/sam/cores/arduino/Arduino.h b/hardware/arduino/sam/cores/arduino/Arduino.h index ced24761a..00b6715b1 100644 --- a/hardware/arduino/sam/cores/arduino/Arduino.h +++ b/hardware/arduino/sam/cores/arduino/Arduino.h @@ -193,6 +193,9 @@ extern const PinDescription g_APinDescription[] ; #include "WMath.h" #include "HardwareSerial.h" #include "wiring_pulse.h" + +#include "Usb.h" + #endif // __cplusplus // Include board variant diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp index b06a88f93..8a9d2410a 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp @@ -540,7 +540,7 @@ uint32_t USBD_Connected(void) //======================================================================= //======================================================================= -USB_ USB; +//USB_ USB; USB_::USB_() { diff --git a/hardware/arduino/sam/cores/arduino/build_gcc/libarduino_arduino_due_x.mk b/hardware/arduino/sam/cores/arduino/build_gcc/libarduino_arduino_due_x.mk index 0a71c2f31..104eeda08 100644 --- a/hardware/arduino/sam/cores/arduino/build_gcc/libarduino_arduino_due_x.mk +++ b/hardware/arduino/sam/cores/arduino/build_gcc/libarduino_arduino_due_x.mk @@ -34,6 +34,7 @@ OUTPUT_BIN = .. # Libraries PROJECT_BASE_PATH = .. PROJECT_BASE_PATH_USB = ../USB +PROJECT_BASE_PATH_USB_HOST = ../../../system/USBHost SYSTEM_PATH = ../../../system CMSIS_ROOT_PATH = $(SYSTEM_PATH)/CMSIS CMSIS_ARM_PATH=$(CMSIS_ROOT_PATH)/CMSIS/Include @@ -45,15 +46,16 @@ VARIANT_PATH = ../../../variants/$(VARIANT) # Files #------------------------------------------------------------------------------- -#vpath %.h $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(SYSTEM_PATH) $(VARIANT_PATH) -vpath %.c $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(VARIANT_PATH) -vpath %.cpp $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) +#vpath %.h $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(PROJECT_BASE_PATH_USB_HOST) $(SYSTEM_PATH) $(VARIANT_PATH) +vpath %.c $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(PROJECT_BASE_PATH_USB_HOST) $(VARIANT_PATH) +vpath %.cpp $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(PROJECT_BASE_PATH_USB_HOST) VPATH+=$(PROJECT_BASE_PATH) INCLUDES = INCLUDES += -I$(PROJECT_BASE_PATH) INCLUDES += -I$(PROJECT_BASE_PATH_USB) +INCLUDES += -I$(PROJECT_BASE_PATH_USB_HOST) INCLUDES += -I$(VARIANT_PATH) INCLUDES += -I$(CMSIS_ARM_PATH) INCLUDES += -I$(CMSIS_ATMEL_PATH) @@ -90,7 +92,7 @@ OUTPUT_PATH=$(OUTPUT_OBJ)_$(VARIANT) #------------------------------------------------------------------------------- # C source files and objects #------------------------------------------------------------------------------- -C_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.c $(PROJECT_BASE_PATH_USB)/*.c) +C_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.c $(PROJECT_BASE_PATH_USB)/*.c $(PROJECT_BASE_PATH_USB_HOST)/*.c) C_OBJ_TEMP = $(patsubst %.c, %.o, $(notdir $(C_SRC))) @@ -102,7 +104,7 @@ C_OBJ=$(filter-out $(C_OBJ_FILTER), $(C_OBJ_TEMP)) #------------------------------------------------------------------------------- # CPP source files and objects #------------------------------------------------------------------------------- -CPP_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.cpp $(PROJECT_BASE_PATH_USB)/*.cpp) +CPP_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.cpp $(PROJECT_BASE_PATH_USB)/*.cpp $(PROJECT_BASE_PATH_USB_HOST)/*.cpp) CPP_OBJ_TEMP = $(patsubst %.cpp, %.o, $(notdir $(CPP_SRC))) diff --git a/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a b/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a deleted file mode 100644 index ad30b43b3..000000000 Binary files a/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a and /dev/null differ diff --git a/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a.txt b/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a.txt deleted file mode 100644 index d5c0cf942..000000000 --- a/hardware/arduino/sam/cores/arduino/libsam_sam3x8e_gcc_dbg.a.txt +++ /dev/null @@ -1,418 +0,0 @@ - -adc.o: -00000000 T adc_configure_power_save -00000000 T adc_configure_sequence -00000000 T adc_configure_timing -00000000 T adc_configure_trigger -00000000 T adc_disable_all_channel -00000000 T adc_disable_anch -00000000 T adc_disable_channel -00000000 T adc_disable_channel_differential_input -00000000 T adc_disable_channel_input_offset -00000000 T adc_disable_interrupt -00000000 T adc_disable_tag -00000000 T adc_disable_ts -00000000 T adc_enable_all_channel -00000000 T adc_enable_anch -00000000 T adc_enable_channel -00000000 T adc_enable_channel_differential_input -00000000 T adc_enable_channel_input_offset -00000000 T adc_enable_interrupt -00000000 T adc_enable_tag -00000000 T adc_enable_ts -00000000 T adc_get_actual_adc_clock -00000000 T adc_get_channel_status -00000000 T adc_get_channel_value -00000000 T adc_get_comparison_mode -00000000 T adc_get_interrupt_mask -00000000 T adc_get_latest_value -00000000 T adc_get_overrun_status -00000000 T adc_get_pdc_base -00000000 T adc_get_status -00000000 T adc_get_tag -00000000 T adc_get_writeprotect_status -00000000 T adc_init -00000000 T adc_set_bias_current -00000000 T adc_set_channel_input_gain -00000000 T adc_set_comparison_channel -00000000 T adc_set_comparison_mode -00000000 T adc_set_comparison_window -00000000 T adc_set_resolution -00000000 T adc_set_writeprotect -00000000 T adc_start -00000000 T adc_start_sequencer -00000000 T adc_stop -00000000 T adc_stop_sequencer - -adc12_sam3u.o: - -interrupt_sam_nvic.o: -00000000 D g_interrupt_enabled - -pio.o: -00000000 T PIO_Clear -00000000 T PIO_Configure -00000000 T PIO_DisableInterrupt -00000000 T PIO_Get -00000000 T PIO_GetOutputDataStatus -00000000 T PIO_PullUp -00000000 T PIO_Set -00000000 T PIO_SetDebounceFilter -00000000 T PIO_SetInput -00000000 T PIO_SetOutput -00000000 T PIO_SetPeripheral - -pmc.o: -00000000 T pmc_clr_fast_startup_input -00000000 T pmc_disable_all_pck -00000000 T pmc_disable_all_periph_clk -00000000 T pmc_disable_interrupt -00000000 T pmc_disable_pck -00000000 T pmc_disable_periph_clk -00000000 T pmc_disable_pllack -00000000 T pmc_disable_udpck -00000000 T pmc_disable_upll_clock -00000000 T pmc_enable_all_pck -00000000 T pmc_enable_all_periph_clk -00000000 T pmc_enable_backupmode -00000000 T pmc_enable_interrupt -00000000 T pmc_enable_pck -00000000 T pmc_enable_periph_clk -00000000 T pmc_enable_pllack -00000000 T pmc_enable_sleepmode -00000000 T pmc_enable_udpck -00000000 T pmc_enable_upll_clock -00000000 T pmc_enable_waitmode -00000000 T pmc_get_interrupt_mask -00000000 T pmc_get_status -00000000 T pmc_get_writeprotect_status -00000000 T pmc_is_locked_pllack -00000000 T pmc_is_locked_upll -00000000 T pmc_is_pck_enabled -00000000 T pmc_is_periph_clk_enabled -00000000 T pmc_mck_set_prescaler -00000000 T pmc_mck_set_source -00000000 T pmc_osc_disable_fastrc -00000000 T pmc_osc_disable_xtal -00000000 T pmc_osc_enable_fastrc -00000000 T pmc_osc_is_ready_32kxtal -00000000 T pmc_osc_is_ready_mainck -00000000 T pmc_pck_set_prescaler -00000000 T pmc_pck_set_source -00000000 T pmc_set_fast_startup_input -00000000 T pmc_set_writeprotect -00000000 T pmc_switch_mainck_to_fastrc -00000000 T pmc_switch_mainck_to_xtal -00000000 T pmc_switch_mck_to_mainck -00000000 T pmc_switch_mck_to_pllack -00000000 T pmc_switch_mck_to_sclk -00000000 T pmc_switch_mck_to_upllck -00000000 T pmc_switch_pck_to_mainck -00000000 T pmc_switch_pck_to_pllack -00000000 T pmc_switch_pck_to_sclk -00000000 T pmc_switch_pck_to_upllck -00000000 T pmc_switch_sclk_to_32kxtal -00000000 T pmc_switch_udpck_to_pllack -00000000 T pmc_switch_udpck_to_upllck - -pwmc.o: -00000024 r .LC0 -00000000 r .LC1 -0000016c r .LC10 -0000019c r .LC11 -000001cc r .LC12 -000001fc r .LC13 -00000204 r .LC14 -00000014 r .LC2 -00000050 r .LC3 -0000007c r .LC4 -000000a8 r .LC5 -000000dc r .LC6 -00000108 r .LC7 -00000134 r .LC8 -00000160 r .LC9 -00000000 t FindClockConfiguration -00000000 T PWMC_ConfigureChannel -00000000 T PWMC_ConfigureChannelExt -00000000 T PWMC_ConfigureClocks -00000000 T PWMC_ConfigureComparisonUnit -00000000 T PWMC_ConfigureEventLineMode -00000000 T PWMC_ConfigureSyncChannel -00000000 T PWMC_DisableChannel -00000000 T PWMC_DisableChannelIt -00000000 T PWMC_DisableIt -00000000 T PWMC_DisableOverrideOutput -00000000 T PWMC_EnableChannel -00000000 T PWMC_EnableChannelIt -00000000 T PWMC_EnableFaultProtection -00000000 T PWMC_EnableIt -00000000 T PWMC_EnableOverrideOutput -00000000 T PWMC_FaultClear -00000000 T PWMC_SetDeadTime -00000000 T PWMC_SetDutyCycle -00000000 T PWMC_SetFaultMode -00000000 T PWMC_SetFaultProtectionValue -00000000 T PWMC_SetOverrideValue -00000000 T PWMC_SetPeriod -00000000 T PWMC_SetSyncChannelUpdatePeriod -00000000 T PWMC_SetSyncChannelUpdateUnlock -00000000 T PWMC_WriteBuffer - U __assert_func -00000000 r __func__.3192 -00000000 r __func__.3203 -00000000 r __func__.3218 -00000000 r __func__.3229 -00000000 r __func__.3240 -00000000 r __func__.3247 -00000000 r __func__.3331 -00000000 r __func__.3337 - -rtc.o: -00000000 r .LC0 -00000010 r .LC1 -0000002c r .LC2 -00000000 T RTC_ClearSCCR -00000000 T RTC_DisableIt -00000000 T RTC_EnableIt -00000000 T RTC_GetDate -00000000 T RTC_GetHourMode -00000000 T RTC_GetSR -00000000 T RTC_GetTime -00000000 T RTC_SetDate -00000000 T RTC_SetDateAlarm -00000000 T RTC_SetHourMode -00000000 T RTC_SetTime -00000000 T RTC_SetTimeAlarm - U __assert_func -00000000 r __func__.3189 -00000000 r __func__.3198 -00000000 r __func__.3203 - -rtt.o: -00000000 r .LC0 -00000010 r .LC1 -0000002c r .LC2 -00000000 T RTT_EnableIT -00000000 T RTT_GetStatus -00000000 T RTT_GetTime -00000000 T RTT_SetAlarm -00000000 T RTT_SetPrescaler - U __assert_func -00000000 r __func__.3196 -00000000 r __func__.3204 - -spi.o: -00000000 T SPI_Configure -00000000 T SPI_ConfigureNPCS -00000000 T SPI_Disable -00000000 T SPI_DisableIt -00000000 T SPI_Enable -00000000 T SPI_EnableIt -00000000 T SPI_GetStatus -00000000 T SPI_IsFinished -00000000 T SPI_Read -00000000 T SPI_Write - U pmc_enable_periph_clk - -tc.o: -00000000 r .LC0 -00000010 r .LC1 -00000000 T TC_Configure -00000000 T TC_FindMckDivisor -00000000 T TC_Start -00000000 T TC_Stop - U __assert_func -00000000 r __func__.3191 -00000000 r __func__.3197 -00000000 r __func__.3203 - -timetick.o: -00000000 T GetTickCount -00000000 t NVIC_SetPriority -00000000 T Sleep -00000000 t SysTick_Config -00000000 T TimeTick_Configure -00000000 T TimeTick_Increment -00000000 T Wait -00000000 b _dwTickCount - -twi.o: -00000000 r .LC0 -00000010 r .LC1 -00000018 r .LC2 -00000024 r .LC3 -00000054 r .LC4 -00000064 r .LC5 -0000007c r .LC6 -0000009c r .LC7 -000000a8 r .LC8 -00000000 T TWI_ByteReceived -00000000 T TWI_ByteSent -00000000 T TWI_ConfigureMaster -00000000 T TWI_ConfigureSlave -00000000 T TWI_DisableIt -00000000 T TWI_EnableIt -00000000 T TWI_GetMaskedStatus -00000000 T TWI_GetStatus -00000000 T TWI_ReadByte -00000000 T TWI_SendSTOPCondition -00000000 T TWI_StartRead -00000000 T TWI_StartWrite -00000000 T TWI_Stop -00000000 T TWI_TransferComplete -00000000 T TWI_WriteByte - U __assert_func -00000000 r __func__.3556 -00000000 r __func__.3571 -00000000 r __func__.3575 -00000000 r __func__.3582 -00000000 r __func__.3586 -00000000 r __func__.3591 -00000000 r __func__.3599 -00000000 r __func__.3613 -00000000 r __func__.3618 -00000000 r __func__.3622 -00000000 r __func__.3627 -00000000 r __func__.3631 - -udp.o: - -udphs.o: - -uotghs.o: -00000000 t NVIC_EnableIRQ -00000000 t NVIC_SetPriority -00000000 T UDD_Attach -00000000 T UDD_ClearIN -00000000 T UDD_ClearOUT -00000000 T UDD_ClearSetupInt -00000000 T UDD_Detach -00000000 T UDD_FifoByteCount -00000000 T UDD_GetFrameNumber -00000000 T UDD_Init -00000000 T UDD_InitEP -00000000 T UDD_InitEndpoints -00000000 T UDD_ReadWriteAllowed -00000000 T UDD_ReceivedSetupInt -00000000 T UDD_Recv -00000000 T UDD_Recv8 -00000000 T UDD_ReleaseRX -00000000 T UDD_ReleaseTX -00000000 T UDD_Send -00000000 T UDD_Send8 -00000000 T UDD_SetAddress -00000000 T UDD_SetStack -00000000 T UDD_Stall -00000000 T UDD_WaitForINOrOUT -00000000 T UDD_WaitIN -00000000 T UDD_WaitOUT -00000000 T UOTGHS_Handler -00000000 t cpu_irq_is_enabled_flags -00000000 t cpu_irq_restore -00000000 t cpu_irq_save - U g_interrupt_enabled -00000000 b gpf_isr - U pmc_enable_periph_clk - U pmc_enable_udpck - U pmc_enable_upll_clock - U pmc_switch_udpck_to_upllck -00000000 b ul_recv_fifo_ptr -00000000 b ul_send_fifo_ptr - -usart.o: -00000000 r .LC0 -00000014 r .LC1 -00000000 T USART_Configure -00000000 T USART_DisableIt -00000000 T USART_EnableIt -00000000 T USART_GetChar -00000000 T USART_GetStatus -00000000 T USART_IsDataAvailable -00000000 T USART_IsRxReady -00000000 T USART_PutChar -00000000 T USART_Read -00000000 T USART_ReadBuffer -00000000 T USART_SetIrdaFilter -00000000 T USART_SetReceiverEnabled -00000000 T USART_SetTransmitterEnabled -00000000 T USART_Write -00000000 T USART_WriteBuffer - U __assert_func -00000000 r __func__.3477 - -wdt.o: -00000000 T WDT_Disable -00000000 T WDT_Enable -00000000 T WDT_GetPeriod -00000000 T WDT_GetStatus -00000000 T WDT_Restart - -system_sam3xa.o: -00000000 D SystemCoreClock -00000000 T SystemCoreClockUpdate -00000000 T SystemInit -00000000 T system_init_flash - -startup_sam3xa.o: -00000000 W ADC_Handler -00000000 W BusFault_Handler -00000000 W CAN0_Handler -00000000 W CAN1_Handler -00000000 W DACC_Handler -00000000 W DMAC_Handler -00000000 W DebugMon_Handler -00000000 T Dummy_Handler -00000000 W EFC0_Handler -00000000 W EFC1_Handler -00000000 W EMAC_Handler -00000000 W HSMCI_Handler -00000000 W HardFault_Handler -00000000 W MemManage_Handler -00000000 W NMI_Handler -00000000 W PIOA_Handler -00000000 W PIOB_Handler -00000000 W PIOC_Handler -00000000 W PIOD_Handler -00000000 W PMC_Handler -00000000 W PWM_Handler -00000000 W PendSV_Handler -00000000 W RSTC_Handler -00000000 W RTC_Handler -00000000 W RTT_Handler -00000000 T Reset_Handler -00000000 W SMC_Handler -00000000 W SPI0_Handler -00000000 W SSC_Handler -00000000 W SUPC_Handler -00000000 W SVC_Handler -00000000 W SysTick_Handler -00000000 W TC0_Handler -00000000 W TC1_Handler -00000000 W TC2_Handler -00000000 W TC3_Handler -00000000 W TC4_Handler -00000000 W TC5_Handler -00000000 W TC6_Handler -00000000 W TC7_Handler -00000000 W TC8_Handler -00000000 W TRNG_Handler -00000000 W TWI0_Handler -00000000 W TWI1_Handler -00000000 W UART_Handler -00000000 W UOTGHS_Handler -00000000 W USART0_Handler -00000000 W USART1_Handler -00000000 W USART2_Handler -00000000 W USART3_Handler -00000000 W UsageFault_Handler -00000000 W WDT_Handler - U __libc_init_array - U _erelocate - U _estack - U _etext - U _ezero - U _sfixed - U _srelocate - U _szero -00000000 R exception_table - U main diff --git a/hardware/arduino/sam/cores/arduino/main.cpp b/hardware/arduino/sam/cores/arduino/main.cpp index dcc6edb6a..818679f18 100644 --- a/hardware/arduino/sam/cores/arduino/main.cpp +++ b/hardware/arduino/sam/cores/arduino/main.cpp @@ -40,7 +40,7 @@ int main( void ) delay(1); #if defined(USBCON) - USB.attach(); + //USB.attach(); #endif setup(); diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/Makefile b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/Makefile new file mode 100644 index 000000000..3f88f26e1 --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (c) 2011 Arduino. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +SUBMAKE_OPTIONS=--no-builtin-rules --no-builtin-variables + +#------------------------------------------------------------------------------- +# Rules +#------------------------------------------------------------------------------- + +all: test_usb_device + +.PHONY: test_usb_device +test: + @echo --- Making test_usb_device + @$(MAKE) DEBUG=1 $(SUBMAKE_OPTIONS) -f test_usb_device.mk + +.PHONY: clean +clean: + @echo --- Cleaning test_usb_device + @$(MAKE) DEBUG=1 $(SUBMAKE_OPTIONS) -f test_usb_device.mk $@ + +.PHONY: debug +debug: + @echo --- Debugging test_usb_device + @$(MAKE) DEBUG=1 $(SUBMAKE_OPTIONS) -f test_usb_device.mk $@ + diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/debug.mk b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/debug.mk new file mode 100644 index 000000000..d0716744a --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/debug.mk @@ -0,0 +1,25 @@ +# +# Copyright (c) 2011 Arduino. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +# Optimization level +# -O1 Optimize +# -O2 Optimize even more +# -O3 Optimize yet more +# -O0 Reduce compilation time and make debugging produce the expected results +# -Os Optimize for size +OPTIMIZATION = -g -O0 -DDEBUG diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/gcc.mk b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/gcc.mk new file mode 100644 index 000000000..36951b468 --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/gcc.mk @@ -0,0 +1,85 @@ +# +# Copyright (c) 2011 Arduino. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +# Tool suffix when cross-compiling +#CROSS_COMPILE = ../../../../tools/CodeSourcery_arm/bin/arm-none-eabi- +#CROSS_COMPILE = C:/CodeSourcery_2011.03-42/bin/arm-none-eabi- +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- + +# Compilation tools +AR = $(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +AS = $(CROSS_COMPILE)as +GDB = $(CROSS_COMPILE)gdb +SIZE = $(CROSS_COMPILE)size +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy + +ifeq ($(OS),Windows_NT) +RM=cs-rm -Rf +else +RM=rm -Rf +endif + +SEP=\\ + +# --------------------------------------------------------------------------------------- +# C Flags + +CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int +CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses +CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused +CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef +CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings +CFLAGS += -Wsign-compare -Waggregate-return -Wstrict-prototypes +CFLAGS += -Wmissing-prototypes -Wmissing-declarations +CFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations +CFLAGS += -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wlong-long +CFLAGS += -Wunreachable-code +CFLAGS += -Wcast-align + +CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls -ffunction-sections -nostdlib -std=c99 +CFLAGS += $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D$(VARIANT) + +# To reduce application size use only integer printf function. +CFLAGS += -Dprintf=iprintf + +# --------------------------------------------------------------------------------------- +# CPP Flags + +CPPFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2 +CPPFLAGS += -Wmain -Wparentheses -Wcast-align -Wunreachable-code +CPPFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused +CPPFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef +CPPFLAGS += -Wshadow -Wpointer-arith -Wwrite-strings +CPPFLAGS += -Wsign-compare -Waggregate-return -Wmissing-declarations +CPPFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations +CPPFLAGS += -Wpacked -Wredundant-decls -Winline -Wlong-long + +#-fno-rtti -fno-exceptions +CPPFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls -ffunction-sections -std=c++98 +CPPFLAGS += $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) + +# To reduce application size use only integer printf function. +CPPFLAGS += -Dprintf=iprintf + +# --------------------------------------------------------------------------------------- +# ASM Flags + +ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/release.mk b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/release.mk new file mode 100644 index 000000000..0d15157f4 --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/release.mk @@ -0,0 +1,25 @@ +# +# Copyright (c) 2011 Arduino. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +# Optimization level +# -O1 Optimize +# -O2 Optimize even more +# -O3 Optimize yet more +# -O0 Reduce compilation time and make debugging produce the expected results +# -Os Optimize for size +OPTIMIZATION = -Os diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/test_usb_device.mk b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/test_usb_device.mk new file mode 100644 index 000000000..336bbc609 --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/build_gcc/test_usb_device.mk @@ -0,0 +1,218 @@ +# +# Copyright (c) 2011 Arduino. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +# Makefile for compiling libArduino +.SUFFIXES: .o .a .c .s + +# putting default variant +ifeq ("$(VARIANT)", "") +#VARIANT=sam3s_ek +#VARIANT=sam3u_ek +VARIANT=arduino_due_x +endif + +ifeq ("$(VARIANT)", "sam3s_ek") +CHIP=__SAM3S4C__ +VARIANT_PATH = ../../../../atmel/sam/variants/$(VARIANT) +else ifeq ("$(VARIANT)", "sam3u_ek") +CHIP=__SAM3U4E__ +VARIANT_PATH = ../../../../atmel/sam/variants/$(VARIANT) +else ifeq ("$(VARIANT)", "sam3x_ek") +CHIP=__SAM3X8H__ +VARIANT_PATH = ../../../../atmel/sam/variants/$(VARIANT) +else ifeq ("$(VARIANT)", "arduino_due_u") +CHIP=__SAM3U4E__ +VARIANT_PATH = ../../../../variants/$(VARIANT) +else ifeq ("$(VARIANT)", "arduino_due_x") +CHIP=__SAM3X8E__ +VARIANT_PATH = ../../../../variants/$(VARIANT) +endif + +TOOLCHAIN=gcc + +#------------------------------------------------------------------------------- +# Path +#------------------------------------------------------------------------------- + +# Libraries +PROJECT_BASE_PATH = ./.. +SYSTEM_PATH = ../../../../system + +ifeq ($(CHIP), __SAM3S4C__) +CHIP_NAME=sam3s4c +CHIP_SERIE=sam3s +else ifeq ($(CHIP), __SAM3U4E__) +CHIP_NAME=sam3u4e +CHIP_SERIE=sam3u +else ifeq ($(CHIP), __SAM3N4C__) +CHIP_NAME=sam3n4c +CHIP_SERIE=sam3n +else ifeq ($(CHIP), __SAM3X8H__) +CHIP_NAME=sam3x8h +CHIP_SERIE=sam3xa +else ifeq ($(CHIP), __SAM3X8E__) +CHIP_NAME=sam3x8e +CHIP_SERIE=sam3xa +else +endif + +CMSIS_ROOT_PATH = $(SYSTEM_PATH)/CMSIS +CMSIS_ARM_PATH=$(CMSIS_ROOT_PATH)/CMSIS/Include +CMSIS_ATMEL_PATH=$(CMSIS_ROOT_PATH)/Device/ATMEL +CMSIS_CHIP_PATH=$(CMSIS_ROOT_PATH)/Device/ATMEL/$(CHIP_SERIE) + +ARDUINO_CORE_PATH=$(PROJECT_BASE_PATH)/.. +ARDUINO_USB_PATH=$(PROJECT_BASE_PATH)/../USB +ARDUINO_USB_HOST_PATH=$(PROJECT_BASE_PATH)/../../../system/USBHost + +# Output directories +OUTPUT_PATH = debug_$(VARIANT) + +#------------------------------------------------------------------------------- +# Files +#------------------------------------------------------------------------------- + +vpath %.h $(PROJECT_BASE_PATH)/.. $(VARIANT_PATH) $(SYSTEM_PATH) $(CMSIS_ARM_PATH) +vpath %.cpp $(PROJECT_BASE_PATH) + +VPATH+=$(PROJECT_BASE_PATH) + +INCLUDES = -I$(PROJECT_BASE_PATH)/.. +INCLUDES += -I$(VARIANT_PATH) +#INCLUDES += -I$(VARIANT_PATH)/.. +#INCLUDES += -I$(SYSTEM_PATH) +INCLUDES += -I$(SYSTEM_PATH)/libsam +INCLUDES += -I$(CMSIS_ARM_PATH) +INCLUDES += -I$(CMSIS_ATMEL_PATH) +INCLUDES += -I$(CMSIS_CHIP_PATH) +INCLUDES += -I$(ARDUINO_USB_PATH) +INCLUDES += -I$(ARDUINO_USB_HOST_PATH) + +#------------------------------------------------------------------------------- +ifdef DEBUG +include debug.mk +else +include release.mk +endif + +#------------------------------------------------------------------------------- +# Tools +#------------------------------------------------------------------------------- + +include $(TOOLCHAIN).mk + +#------------------------------------------------------------------------------- +ifdef DEBUG +OUTPUT_OBJ=debug +LIBS_POSTFIX=dbg +else +OUTPUT_OBJ=release +LIBS_POSTFIX=rel +endif + +OUTPUT_BIN=test_$(TOOLCHAIN)_$(LIBS_POSTFIX) +LIBS=-Wl,--start-group -lgcc -lc -lstdc++ -lsam_$(CHIP_NAME)_$(TOOLCHAIN)_$(LIBS_POSTFIX) -larduino_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX) -lvariant_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX) -Wl,--end-group + +LIB_PATH =-L$(PROJECT_BASE_PATH)/.. +LIB_PATH+=-L=/lib/thumb2 +#LIB_PATH+=-L=/../lib/gcc/arm-none-eabi/4.5.2/thumb2 + +LDFLAGS= -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols + +#------------------------------------------------------------------------------- +# CPP source files and objects +#------------------------------------------------------------------------------- +CPP_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.cpp) + +CPP_OBJ_TEMP = $(patsubst %.cpp, %.o, $(notdir $(CPP_SRC))) + +# during development, remove some files +CPP_OBJ_FILTER= + +CPP_OBJ=$(filter-out $(CPP_OBJ_FILTER), $(CPP_OBJ_TEMP)) + +#------------------------------------------------------------------------------- +# Rules +#------------------------------------------------------------------------------- +all: test + +test: create_output libsam_$(CHIP_NAME)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a libarduino_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a libvariant_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a $(OUTPUT_BIN) + + +.PHONY: create_output +create_output: + @echo --- Preparing $(VARIANT) files in $(OUTPUT_PATH) $(OUTPUT_BIN) +# @echo ------------------------- +# @echo *$(INCLUDES) +# @echo ------------------------- +# @echo *$(C_SRC) +# @echo ------------------------- +# @echo *$(C_OBJ) +# @echo ------------------------- +# @echo *$(addprefix $(OUTPUT_PATH)/, $(C_OBJ)) +# @echo ------------------------- +# @echo *$(CPP_SRC) +# @echo ------------------------- +# @echo *$(CPP_OBJ) +# @echo ------------------------- +# @echo *$(addprefix $(OUTPUT_PATH)/, $(CPP_OBJ)) +# @echo ------------------------- +# @echo *$(A_SRC) +# @echo ------------------------- + + -@mkdir $(OUTPUT_PATH) 1>NUL 2>&1 + +$(addprefix $(OUTPUT_PATH)/,$(CPP_OBJ)): $(OUTPUT_PATH)/%.o: %.cpp +# @"$(CC)" -c $(CPPFLAGS) $< -o $@ + @"$(CXX)" -c $(CPPFLAGS) $< -o $@ +# @"$(CXX)" -v -c $(CPPFLAGS) $< -o $@ + +$(OUTPUT_BIN): $(addprefix $(OUTPUT_PATH)/, $(C_OBJ)) $(addprefix $(OUTPUT_PATH)/, $(CPP_OBJ)) $(addprefix $(OUTPUT_PATH)/, $(A_OBJ)) + @"$(CC)" $(LIB_PATH) $(LDFLAGS) -T"$(VARIANT_PATH)/linker_scripts/gcc/flash.ld" -Wl,-Map,$(OUTPUT_PATH)/$@.map -o $(OUTPUT_PATH)/$@.elf $^ $(LIBS) +# @"$(CC)" $(LIB_PATH) $(LDFLAGS) -T"$(VARIANT_PATH)/linker_scripts/gcc/sram.ld" -Wl,-Map,$(OUTPUT_PATH)/$@.map -o $(OUTPUT_PATH)/$@.elf $^ $(LIBS) + @"$(NM)" $(OUTPUT_PATH)/$@.elf >$(OUTPUT_PATH)/$@.elf.txt + @"$(OBJCOPY)" -O binary $(OUTPUT_PATH)/$@.elf $(OUTPUT_PATH)/$@.bin + $(SIZE) $^ $(OUTPUT_PATH)/$@.elf + +.PHONY: clean +clean: + @echo --- Cleaning test files + -@$(RM) $(OUTPUT_PATH) 1>NUL 2>&1 + +# -$(RM) $(OUTPUT_PATH)/test.o +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).elf +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).elf.txt +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).bin +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).map + +debug: test + @"$(GDB)" -x "$(VARIANT_PATH)/debug_scripts/gcc/$(VARIANT)_flash.gdb" -ex "reset" -readnow -se $(OUTPUT_PATH)/$(OUTPUT_BIN).elf +# @"$(GDB)" -w -x "$(VARIANT_PATH)/debug_scripts/gcc/$(VARIANT)_sram.gdb" -ex "reset" -readnow -se $(OUTPUT_PATH)/$(OUTPUT_BIN).elf + +libsam_$(CHIP_NAME)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a: + @echo Building $@ + @$(MAKE) -C $(SYSTEM_PATH)/libsam/build_gcc -f Makefile $@ + +libarduino_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a: + @echo Building $@ + $(MAKE) -C $(ARDUINO_CORE_PATH)/build_gcc -f Makefile $(VARIANT) + +libvariant_$(VARIANT)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a: + @echo Building $@ + $(MAKE) -C $(VARIANT_PATH)/build_gcc -f Makefile $(VARIANT) + diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h b/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h new file mode 100644 index 000000000..02df7d116 --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h @@ -0,0 +1,288 @@ +#ifndef _DESCRIPTOR_PARSER_ +#define _DESCRIPTOR_PARSER_ + +typedef void (*PARSE)( uint8_t* buffer, uint8_t pkt_size ); + +/* Common Messages */ +const char descr_len[] = "Descriptor Length:\t"; +const char descr_type[] = "Descriptor type:\t"; +const char class_str[] = "Class:\t\t\t"; +const char subclass_str[] = "Subclass:\t\t"; +const char protocol_str[] = "Protocol:\t\t"; +const char maxpktsize_str[] = "Max.packet size:\t"; +const char unk_msg[] = " Unknown"; +const char reserved_msg[] = "Reserved"; +const char rcode_error_msg[] = "\r\nRequest error. Return code: "; + +/* Endpoint attributes */ +const char control_tr[] = "Control"; +const char iso_tr[] = "Isochronous"; +const char bulk_tr[] = "Bulk"; +const char int_tr[] = "Interrupt"; + +const char* transfer_types[] = +{ + control_tr, + iso_tr, + bulk_tr, + int_tr +}; + +const char nosync_type[] = "No Synchronization"; +const char async_type[] = "Asynchronous"; +const char adaptive_type[] = "Adaptive"; +const char sync_type[] = "Synchronous"; + +const char* sync_types[] = +{ + nosync_type, + async_type, + adaptive_type, + sync_type +}; + +const char data_usage[] = "Data"; +const char feedback_usage[] = "Feedback"; +const char implicit_usage[] = "Implicit Feedback Data"; +const char reserved_usage[] = "Reserved"; + +const char* usage_types[] = +{ + data_usage, + feedback_usage, + implicit_usage, + reserved_usage +}; + +/* HID Country Codes */ +const char notsupported_cc[] = "Not Supported"; +const char arabic_cc[] = "Arabic"; +const char belgian_cc[] = "Belgian"; +const char canadianbi_cc[] = "Canadian-Bilingual"; +const char canadianfr_cc[] = "Canadian-French"; +const char czech_cc[] = "Czech Republic"; +const char danish_cc[] = "Danish"; +const char finnish_cc[] = "Finnish"; +const char french_cc[] = "French"; +const char german_cc[] = "German"; +const char greek_cc[] = "Greek"; +const char hebrew_cc[] = "Hebrew"; +const char hungary_cc[] = "Hungary"; +const char intl_cc[] = "International (ISO)"; +const char italian_cc[] = "Italian"; +const char japan_cc[] = "Japan (Katakana)"; +const char korean_cc[] = "Korean"; +const char latam_cc[] = "Latin American"; +const char dutch_cc[] = "Netherlands/Dutch"; +const char norwegian_cc[] = "Norwegian"; +const char persian_cc[] = "Persian (Farsi)"; +const char poland_cc[] = "Poland"; +const char portuguese_cc[] = "Portuguese"; +const char russia_cc[] = "Russia"; +const char slovakia_cc[] = "Slovakia"; +const char spanish_cc[] = "Spanish"; +const char swedish_cc[] = "Swedish"; +const char swiss_fr_cc[] = "Swiss/French"; +const char swiss_ger_cc[] = "Swiss/German"; +const char swiss_cc[] = "Switzerland"; +const char taiwan_cc[] = "Taiwan"; +const char turkish_q_cc[] = "Turkish-Q"; +const char uk_cc[] = "UK"; +const char us_cc[] = "US"; +const char yugo_cc[] = "Yugoslavia"; +const char turkish_f_cc[] = "Turkish-F"; + +const char* HID_Country_Codes[] = +{ + notsupported_cc, + arabic_cc, + belgian_cc, + canadianbi_cc, + canadianfr_cc, + czech_cc, + danish_cc, + finnish_cc, + french_cc, + german_cc, + greek_cc, + hebrew_cc, + hungary_cc, + intl_cc, + italian_cc, + japan_cc, + korean_cc, + latam_cc, + dutch_cc, + norwegian_cc, + persian_cc, + poland_cc, + portuguese_cc, + russia_cc, + slovakia_cc, + spanish_cc, + swedish_cc, + swiss_fr_cc, + swiss_ger_cc, + swiss_cc, + taiwan_cc, + turkish_q_cc, + uk_cc, + us_cc, + yugo_cc, + turkish_f_cc +}; + +/* HID report descriptor parser string definitions */ +/* Item type strings */ +const char btype_main[] = "Main"; +const char btype_global[] = "Global"; +const char btype_local[] = "Local"; +const char btype_reserved[] = "Reserved"; + +/* Item types strings array. Array index corresponds to bType */ +const char* btypes[] = +{ + btype_main, + btype_global, + btype_local, + btype_reserved +}; + +/* Main Item Tag Strings */ +const char main_tag_input[] = "Input "; +const char main_tag_output[] = "Output "; +const char main_tag_collection[] = "Collection "; +const char main_tag_feature[] = "Feature "; +const char main_tag_endcoll[] = "End Collection\r\n"; + +/* Main Item Tags Strings Array */ +const char* maintags[] = +{ + main_tag_input, + main_tag_output, + main_tag_collection, + main_tag_feature, + main_tag_endcoll +}; + +/* Global Item Tag Strings */ +const char global_tag_usagepage[] = "Usage Page "; +const char global_tag_logmin[] = "Logical Minimum "; +const char global_tag_logmax[] = "Logical Maximum "; +const char global_tag_physmin[] = "Physical Minimum "; +const char global_tag_physmax[] = "Physical Maximum "; +const char global_tag_unitexp[] = "Unit Exponent "; +const char global_tag_unit[] = "Unit "; +const char global_tag_repsize[] = "Report Size "; +const char global_tag_repid[] = "Report ID "; +const char global_tag_repcount[] = "Report Count "; +const char global_tag_push[] = "Push"; +const char global_tag_pop[] = "Pop"; + +/* Global Item Tag Strings Array */ +const char* globaltags[] = +{ + global_tag_usagepage, + global_tag_logmin, + global_tag_logmax, + global_tag_physmin, + global_tag_physmax, + global_tag_unitexp, + global_tag_unit, + global_tag_repsize, + global_tag_repid, + global_tag_repcount, + global_tag_push, + global_tag_pop +}; + +/* Local Item Tag Strings */ +const char local_tag_usage[] = "Usage "; +const char local_tag_usagemin[] = "Usage Minimum "; +const char local_tag_usagemax[] = "Usage Maximum "; +const char local_tag_desidx[] = "Designator Index "; +const char local_tag_desmin[] = "Designator Minimum "; +const char local_tag_desmax[] = "Designator Maximum "; +const char local_tag_stridx[] = "String Index "; +const char local_tag_strmin[] = "String Minimum "; +const char local_tag_strmax[] = "String Maximum "; +const char local_tag_delimiter[] = "Delimiter "; + +/* Local Item Tag Strings Array */ +const char* localtags[] = +{ + local_tag_usage, + local_tag_usagemin, + local_tag_usagemax, + local_tag_desidx, + local_tag_desmin, + local_tag_desmax, + local_tag_stridx, + local_tag_strmin, + local_tag_strmax, + local_tag_delimiter +}; + +/* Collection Types Strings */ +const char coll_phy[] = "Physical (group of axes)"; +const char coll_app[] = "Application (mouse, keyboard)"; +const char coll_log[] = "Logical (interrelated data)"; +const char coll_rep[] = "Report"; +const char coll_arr[] = "Named Array"; +const char coll_usw[] = "Usage Switch"; +const char coll_umod[] = "Usage Modifier"; + +/* Collection Types Strings Array */ +const char* collections[] = +{ + coll_phy, + coll_app, + coll_log, + coll_rep, + coll_arr, + coll_usw, + coll_umod +}; + +/* Usage Pages Strings */ +const char up_undef[] = "Undefined"; +const char up_gendesk[] = "Generic Desktop Controls"; +const char up_sim[] = "Simulation Controls"; +const char up_vr[] = "VR Controls"; +const char up_sport[] = "Sport Controls"; +const char up_game[] = "Game Controls"; +const char up_gendev[] = "Generic Device Controls"; +const char up_kbd[] = "Keyboard/Keypad"; +const char up_led[] = "LEDs"; +const char up_button[] = "Button"; +const char up_ord[] = "Ordinal"; +const char up_tele[] = "Telephony"; +const char up_cons[] = "Consumer"; +const char up_dig[] = "Digitizer"; +//const char up_res[] = "Reserved"; +const char up_pid[] = "PID Page"; +const char up_uni[] = "Unicode"; + +/* Usage Pages Strings Array */ +const char * usage_pages[] = +{ + up_undef, + up_gendesk, + up_sim, + up_vr, + up_sport, + up_game, + up_gendev, + up_kbd, + up_led, + up_button, + up_ord, + up_tele, + up_cons, + up_dig, + reserved_msg, + up_pid, + up_uni +}; + +#endif //_DESCRIPTOR_PARSER_ diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_device.cpp b/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_device.cpp new file mode 100644 index 000000000..5ea2fbc7e --- /dev/null +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_device.cpp @@ -0,0 +1,780 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "variant.h" +#include +#include "descriptor_parser.h" + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 +#define DEVADDR 1 + +#define getReportDescr(addr, ep, nbytes, buf) Usb.ctrlReq(addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, buf) + +USBHost Usb; + +/* Forward declarations */ +void HIDreport_parse(uint8_t* buffer, uint8_t pkt_size); +void print_mainbitfield(uint8_t byte_toparse); +void printunkdescr(uint8_t* descr_ptr); +void printhid_descr(uint8_t* descr_ptr); +void printepdescr(uint8_t* descr_ptr); +void printintfdescr(uint8_t* descr_ptr); +void printconfdescr(uint8_t* descr_ptr); +uint32_t getconfdescr(uint32_t addr, uint32_t conf); +void classname_parse(byte class_number); +uint32_t getstrdescr(uint32_t addr, uint32_t idx); +uint32_t getdevdescr(uint32_t addr); + +_Pragma("pack(1)") + +typedef struct +{ + uint8_t bDescriptorType; + uint16_t wDescriptorLength; +} HID_CLASS_DESCRIPTOR; + +_Pragma("pack()") + +void setup() +{ + cpu_irq_enable(); + printf("\r\nProgram started:\r\n"); + delay(200); +} + +void loop() +{ + uint8_t tmpbyte = 0; + + Usb.Task(); + + // If state configuring or higher + if (Usb.getUsbTaskState() >= USB_STATE_CONFIGURING) + { + // Printing device descriptor + printf("\r\nDevice addressed...\r\n"); + printf("Requesting device descriptor.\r\n"); + + // Number of configurations, 0 if error + tmpbyte = getdevdescr(DEVADDR); + if (tmpbyte == 0) + { + printf("\r\nDevice descriptor cannot be retrieved. Program Halted!\r\n"); + while (1) + ; + } + + // Print configuration descriptors for all configurations + for (uint8_t i = 0; i < tmpbyte; i++) + { + getconfdescr(DEVADDR, i); + } + + while (1) + ; + } +} + +/** + * Get device descriptor. + * Return number of configurations or zero on error. + */ +uint32_t getdevdescr(uint32_t addr) +{ + USB_DEVICE_DESCRIPTOR buf; + uint32_t rcode; + + rcode = Usb.getDevDescr(addr, 0, 0x12, (uint8_t*)&buf); + if (rcode) + { + printf("\r\n%s %lu\r\n", rcode_error_msg, rcode); + return 0; + } + printf("\r\nDevice descriptor: \r\n"); + + // Descriptor length + printf("%s0x%x\r\n", descr_len, buf.bLength); + + // Descriptor type + printf("%s0x%x\r\n", descr_type, buf.bDescriptorType); + + // USB Version + printf("USB version:\t\t0x%x\r\n", buf.bcdUSB); + + // Device class + printf("%s0x%x", class_str, buf.bDeviceClass); + classname_parse(buf.bDeviceClass); + printf("\r\n"); + + // Device Subclass + printf("%s0x%x\r\n", subclass_str, buf.bDeviceSubClass); + + // Device Protocol + printf("%s0x%x\r\n", protocol_str, buf.bDeviceProtocol); + + // Max.packet size + printf("%s0x%x\r\n", maxpktsize_str, buf.bMaxPacketSize0); + + // VID + printf("Vendor ID:\t\t0x%x\r\n", buf.idVendor); + + // PID + printf("Product ID:\t\t0x%x\r\n", buf.idProduct); + + // Revision + printf("Revision ID:\t\t0x%x\r\n", buf.bcdDevice); + + // Mfg.string + printf("Mfg.string index:\t0x%x", buf.iManufacturer); + getstrdescr(addr, buf.iManufacturer); + + // Prod.string + printf("Prod.string index:\t0x%x", buf.iProduct); + getstrdescr(addr, buf.iProduct); + + // Serial number string + printf("Serial number index:\t0x%x", buf.iSerialNumber); + getstrdescr(addr, buf.iSerialNumber); + + // Number of configurations + printf("Number of conf.:\t0x%x\r\n", buf.bNumConfigurations); + + return buf.bNumConfigurations; +} + +/** + * Get string descriptor. + * Takes device address and string index. + */ +uint32_t getstrdescr(uint32_t addr, uint32_t idx) +{ + uint8_t buf[BUFSIZE]; + uint32_t rcode; + uint32_t length; + uint32_t i; + uint16_t langid; + + if (idx == 0) + { + // Don't try to get index zero + printf("\r\n"); + return 0; + } + + rcode = Usb.getStrDescr(addr, 0, 1, 0, 0, buf); + // Get language table length + if (rcode) + { + printf("\r\nError retrieving LangID table length!\r\n"); + return rcode; + } + + // Length is the first byte + length = buf[0]; + // Get language table + rcode = Usb.getStrDescr(addr, 0, length, 0, 0, buf); + if (rcode) + { + printf("\r\nError retrieving LangID table!\r\n"); + return rcode; + } + + // Get first langid + langid = buf[3] << 8; + // Bytes are swapped to account for endiannes + langid |= (buf[2] & 0xff); + + rcode = Usb.getStrDescr(addr, 0, 1, idx, langid, buf); + if (rcode) + { + printf("\r\nError retrieving string length!\r\n"); + return rcode; + } + + length = (buf[0] < 254 ? buf[0] : 254); + printf(" Length: %lu", length); + rcode = Usb.getStrDescr(addr, 0, length, idx, langid, buf); + if (rcode) + { + printf("\r\nError retrieving string!\r\n"); + return rcode; + } + + printf(" Contents: "); + for (i = 2; i < length; i += 2) + { + printf("%c", buf[i]); + } + printf("\r\n"); + + return idx; +} + + +/** + * Returns string to class name + */ +void classname_parse(uint8_t class_number) +{ + switch(class_number) { + case 0x00: + printf(" Use class information in the Interface Descriptor"); + break; + case 0x01: + printf(" Audio"); + break; + case 0x02: + printf(" Communications and CDC Control"); + break; + case 0x03: + printf(" HID (Human Interface Device)"); + break; + case 0x05: + printf(" Physical"); + break; + case 0x06: + printf(" Image"); + break; + case 0x07: + printf(" Printer"); + break; + case 0x08: + printf(" Mass Storage"); + break; + case 0x09: + printf(" Hub"); + break; + case 0x0a: + printf(" CDC-Data"); + break; + case 0x0b: + printf(" Smart Card"); + break; + case 0x0d: + printf(" Content Security"); + break; + case 0x0e: + printf(" Video"); + break; + case 0x0f: + printf(" Personal Healthcare"); + break; + case 0xdc: + printf("Diagnostic Device"); + break; + case 0xe0: + printf(" Wireless Controller"); + break; + case 0xef: + printf(" Miscellaneous"); + break; + case 0xfe: + printf(" Application Specific"); + break; + case 0xff: + printf(" Vendor Specific"); + break; + default: + break; + } +} + + +/** + * Print configuration descriptor. + */ +uint32_t getconfdescr(uint32_t addr, uint32_t conf) +{ + uint8_t buf[BUFSIZE]; + uint8_t* buf_ptr = buf; + uint32_t rcode = 0; + uint8_t confdescr_length = 0; + uint8_t confdescr_type = 0; + uint32_t total_length = 0; + + printf("\r\nConfiguration number %lu:\r\n", conf); + + rcode = Usb.getConfDescr(addr, 0, 4, conf, buf); //get total length + if (rcode) + { + printf("\r\nError retrieving configuration length. Error code %lu\r\n", rcode); + return(0); + } + + total_length = buf[3] << 8; + total_length |= (buf[2] & 0xff); + + if (total_length > BUFSIZE) + { + // Check if total length is larger than buffer + printf("Total length truncated to %d bytes\r\n", BUFSIZE); + total_length = BUFSIZE; + } + + // Get the whole descriptor + rcode = Usb.getConfDescr(addr, 0, total_length, conf, buf); + + while (buf_ptr < buf + total_length) + { + // Parsing descriptors + confdescr_length = *(buf_ptr); + confdescr_type = *(buf_ptr + 1); + switch (confdescr_type) + { + case(USB_DESCRIPTOR_CONFIGURATION): + printconfdescr(buf_ptr); + break; + case(USB_DESCRIPTOR_INTERFACE): + printintfdescr(buf_ptr); + break; + case(USB_DESCRIPTOR_ENDPOINT): + printepdescr(buf_ptr); + break; + case(HID_DESCRIPTOR_HID): + printhid_descr(buf_ptr); + break; + default: + printunkdescr(buf_ptr); + break; + } + + // Advance buffer pointer + buf_ptr = (buf_ptr + confdescr_length); + } + + return 0; +} + +/** + * Print configuration descriptor. + */ +void printconfdescr(uint8_t* descr_ptr) +{ + USB_CONFIGURATION_DESCRIPTOR* conf_ptr = (USB_CONFIGURATION_DESCRIPTOR*)descr_ptr; + uint8_t tmpbyte = 0; + + printf("\r\n\nConfiguration descriptor:\r\n"); + printf("Total length:\t\t%d\r\n", conf_ptr->wTotalLength); + + printf("\r\nNumber of interfaces:\t%d\r\n", conf_ptr->bNumInterfaces); + + printf("Configuration value:\t%d\r\n", conf_ptr->bConfigurationValue); + + printf("Configuration string:\t"); + tmpbyte = conf_ptr->iConfiguration; + printf("0x%x", tmpbyte); + getstrdescr(DEVADDR, tmpbyte); + printf("Attributes:\t\t"); + tmpbyte = conf_ptr->bmAttributes; + printf("0x%x", tmpbyte); + + if (tmpbyte & 0x40) + { + // D6 + printf(" Self-powered\r\n"); + } + + if (tmpbyte & 0x20) + { + // D5 + printf(" Remote Wakeup\r\n"); + } + + printf("Max.power:\t\t"); + tmpbyte = conf_ptr->bMaxPower; + printf("0x%x", tmpbyte); + printf(" "); + printf("%d", (tmpbyte * 2)); + printf("ma\r\n"); +} + +/** + * Print interface descriptor. + */ +void printintfdescr(uint8_t* descr_ptr) +{ + USB_INTERFACE_DESCRIPTOR* intf_ptr = (USB_INTERFACE_DESCRIPTOR*)descr_ptr; + uint8_t tmpbyte = 0; + + printf("\r\nInterface descriptor:\r\n"); + printf("Interface number:\t%d\r\n", intf_ptr->bInterfaceNumber); + printf("Alternate setting:\t%d\r\n", intf_ptr->bAlternateSetting); + printf("Endpoints:\t\t%d\r\n", intf_ptr->bNumEndpoints); + + printf("%s", class_str); + tmpbyte = intf_ptr->bInterfaceClass; + printf("0x%x", tmpbyte); + classname_parse(tmpbyte); + printf("\r\n"); + + printf("%s%d\r\n", subclass_str, intf_ptr->bInterfaceSubClass); + printf("%s%d\r\n", protocol_str, intf_ptr->bInterfaceProtocol); + + printf("Interface string:\t"); + tmpbyte = intf_ptr->iInterface; + printf("0x%x", tmpbyte); + getstrdescr(DEVADDR, tmpbyte); +} + +/** + * Print endpoint descriptor. + */ +void printepdescr(uint8_t* descr_ptr) +{ + USB_ENDPOINT_DESCRIPTOR* ep_ptr = (USB_ENDPOINT_DESCRIPTOR*)descr_ptr; + uint8_t tmpbyte = 0; + + printf("\r\nEndpoint descriptor:\r\n"); + printf("Endpoint address:\t"); + tmpbyte = ep_ptr->bEndpointAddress; + printf("0x%x", tmpbyte & 0x0f); + printf(" Direction: "); + (tmpbyte & 0x80) ? printf("IN\r\n") : printf("OUT\r\n"); + + printf("Attributes:\t\t"); + tmpbyte = ep_ptr->bmAttributes; + printf("0x%x", tmpbyte); + printf(" Transfer type: %s", transfer_types[(tmpbyte & 0x03)]); + + if ((tmpbyte & 0x03) == 1) + { + // Isochronous Transfer + printf(", Sync Type: "); + printf("%s", sync_types[(tmpbyte & 0x0c)]); + printf(", Usage Type: "); + printf("%s", usage_types[(tmpbyte & 0x30)]); + } + printf("\r\n"); + printf("%s%d\r\n", maxpktsize_str, ep_ptr->wMaxPacketSize); + + printf("Polling interval:\t"); + tmpbyte = ep_ptr->bInterval; + printf("0x%x", tmpbyte); + printf(" "); + printf("%d", tmpbyte); + printf(" ms\r\n"); +} + +/** + * Print HID descriptor. + */ +void printhid_descr(uint8_t* descr_ptr) +{ + //PARSE pf = HIDreport_parse; + USB_HID_DESCRIPTOR* hid_ptr = (USB_HID_DESCRIPTOR*)descr_ptr; + uint8_t tmpbyte = 0; + + printf("\r\nHID descriptor:\r\n"); + printf("Descriptor length:\t"); + tmpbyte = hid_ptr->bLength; + printf("0x%x %d bytes\r\n", tmpbyte, tmpbyte); + printf("HID version:\t\t0x%x\r\n", hid_ptr->bcdHID); + tmpbyte = hid_ptr->bCountryCode; + printf("Country Code:\t\t%d ", tmpbyte); + (tmpbyte > 35) ? printf("Reserved\r\n") : printf("%s\r\n", HID_Country_Codes[tmpbyte]); + tmpbyte = hid_ptr->bNumDescriptors; + printf("Class Descriptors:\t%d\r\n", tmpbyte); + + // Printing class descriptors + // Advance buffer pointer + descr_ptr += 6; + for (uint8_t i = 0; i < tmpbyte; i++) + { + uint8_t tmpdata = 0; + HID_CLASS_DESCRIPTOR* hidclass_ptr = (HID_CLASS_DESCRIPTOR*)descr_ptr; + tmpdata = hidclass_ptr->bDescriptorType; + printf("Class Descriptor Type:\t0x%x", tmpdata); + + if ((tmpdata < 0x21) || (tmpdata > 0x2f)) + { + printf(" Invalid"); + } + + switch(tmpdata) + { + case 0x21: + printf(" HID\r\n"); + break; + case 0x22: + printf(" Report\r\n"); + break; + case 0x23: + printf(" Physical\r\n"); + break; + default: + printf(" Reserved\r\n"); + break; + } + + printf("Class Descriptor Size: %d bytes\r\n", hidclass_ptr->wDescriptorLength); + + printf("\r\nHID report descriptor:\r\n"); + uint8_t buf[hidclass_ptr->wDescriptorLength]; + getReportDescr(DEVADDR, 0 , hidclass_ptr->wDescriptorLength, (uint8_t*)&buf); + HIDreport_parse(buf, hidclass_ptr->wDescriptorLength); + + // Advance to the next record + descr_ptr += 3; + } + printf("\r\n"); +} + +/** + * Print unknown descriptor. + */ +void printunkdescr(uint8_t* descr_ptr) +{ + uint8_t length = *descr_ptr; + uint32_t i = 0; + + printf("\r\nUnknown descriptor:\r\n"); + printf("Length:\t\t%d\r\n", *descr_ptr); + printf("Type:\t\t %d\r\n", *(descr_ptr + 1)); + printf("Contents:\t"); + descr_ptr += 2; + + for (i = 0; i < length; i++) + { + printf("%d", *descr_ptr); + descr_ptr++; + } + + printf("\r\n"); +} + +/** + * Print bitfields in main items. + */ +void print_mainbitfield(uint8_t byte_toparse) +{ + (byte_toparse & 0x01) ? printf("Constant,") : printf("Data,"); //bit 0 + (byte_toparse & 0x02) ? printf("Variable,") : printf("Array,"); //bit 1 + (byte_toparse & 0x04) ? printf("Relative,") : printf("Absolute,"); //... + (byte_toparse & 0x08) ? printf("Wrap,") : printf("No Wrap,"); + (byte_toparse & 0x10) ? printf("Non Linear,") : printf("Linear,"); + (byte_toparse & 0x20) ? printf("No preferred,") : printf("Preferred State,"); + (byte_toparse & 0x40) ? printf("Null State,") : printf("No Null Position,"); //bit 6 + (byte_toparse & 0x40) ? printf("Volatile(ignore for Input),") : printf("Non-volatile(Ignore for Input),"); //bit 7 +} + +/** + * HID Report Desriptor Parser Callback. + * Called repeatedly from Control transfer function. + */ +void HIDreport_parse(uint8_t* buffer, uint8_t pkt_size) +{ +#define B_SIZE 0x03 //bSize bitmask +#define B_TYPE 0x0c //bType bitmask +#define B_TAG 0xf0 //bTag bitmask + + // Parser states + enum STATE { ITEM_START, DATA_PARSE }; + static STATE state = ITEM_START; + static uint8_t databytes_left = 0; + static uint8_t databytes_left2 = 0; + static uint8_t prefix; //item prefix - type and tag + uint8_t byte_toparse; + uint8_t bType; + uint8_t tmpbyte; + uint32_t i = 0, j = 0; + + while (1) + { + if (i < pkt_size) + { + i = i + 1; + byte_toparse = buffer[i]; + } + else + { + return; + } + + switch(state) + { + // Start of the record + case ITEM_START: + // Store prefix for databyte parsing + prefix = byte_toparse >> 2; + tmpbyte = byte_toparse & B_SIZE; + + // Get item length + (tmpbyte == 0x03) ? databytes_left = 4 : databytes_left = tmpbyte; + if (databytes_left) + { + // Read bytes after prefix + state = DATA_PARSE; + } + printf("bSize: %d", databytes_left); + databytes_left2 = databytes_left; + + // Get item type + bType = (byte_toparse & B_TYPE) >> 2; + printf(" bType: %s", btypes[bType]); + + // Get item tag + printf("\t\tbTag: "); + tmpbyte = (byte_toparse & B_TAG) >> 4 ; + switch(bType) + { + case 0: // Main + if (tmpbyte < 0x08) + { + printf("Invalid Tag"); + } + else if (tmpbyte > 0x0c) + { + printf("%s", reserved_msg); + } + else + { + printf("%s", maintags[tmpbyte - 8]); + } + break; + + case 1: // Global + (tmpbyte > 0x0b) ? printf("%s", reserved_msg) : printf("%s", globaltags[tmpbyte]); + break; + + case 2: // Local + (tmpbyte > 0x0a) ? printf("%s", reserved_msg) : printf("%s", localtags[tmpbyte]); + break; + + default: + break; + } + break; + + case DATA_PARSE: + switch(prefix) + { + case 0x20: // Main Input + case 0x24: // Main Output + case 0x2c: // Main Feature + // TODO: add parsing 8th bit + print_mainbitfield(byte_toparse); + break; + + case 0x28: //Main Collection + if ((byte_toparse > 0x06) && (byte_toparse < 0x80)) + { + printf("%s", reserved_msg); + } + else if ((byte_toparse > 0x7f) && (byte_toparse <= 0xff)) + { + printf("Vendor-defined"); + } + else + { + printf("%s", collections[byte_toparse]); + } + break; + + //case 0x30: //Main End Collection + case 0x01: //Global Usage Page + switch(byte_toparse) + { + // See HID Usage Tables doc v.1.12 page 14 + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + printf("%s", usage_pages[byte_toparse]); + break; + + case 0x14: + printf("Alphanumeric Display"); + break; + + case 0x40: + printf("Medical Instruments"); + break; + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + printf("Monitor page"); + break; + + case 0x84: + case 0x85: + case 0x86: + case 0x87: + printf("Power page"); + break; + + case 0x8c: + printf("Bar Code Scanner page"); + break; + + case 0x8d: + printf("Scale page"); + break; + + case 0x8e: + printf("Magnetic Stripe Reading (MSR) Devices"); + break; + + case 0x8f: + printf("Reserved Point of Sale pages"); + break; + + case 0x90: + printf("Camera Control Page"); + break; + + case 0x91: + printf("Arcade Page"); + break; + + default: + break; + } + } + + databytes_left--; + + if (!databytes_left) + { + printf(" (data=0x"); + for (j = 0; j < databytes_left2; ++j) + printf("%02x", buffer[i - j]); + printf(")\r\n"); + + state = ITEM_START; + } + break; + } + } +} diff --git a/hardware/arduino/sam/sam.bat b/hardware/arduino/sam/sam.bat index e142728c9..27441877b 100644 --- a/hardware/arduino/sam/sam.bat +++ b/hardware/arduino/sam/sam.bat @@ -2,9 +2,9 @@ set Path=%ARM_GCC_TOOLCHAIN% export Path start "libsam" /d"system\libsam\build_gcc" /max "cd" -start "libarduino" /d"cores\sam\build_gcc" /max "cd" +start "libarduino" /d"cores\arduino\build_gcc" /max "cd" rem start "libvariant Arduino Due U" /d"variants\arduino_due_u\build_gcc" /max "cd" start "libvariant Arduino Due X" /d"variants\arduino_due_x\build_gcc" /max "cd" -start "libvariant ADK2" /d"..\..\google\sam\variants\adk2\build_gcc" /max "cd" -start "libvariant SAM3X-EK" /d"..\..\atmel\sam\variants\sam3x_ek\build_gcc" /max "cd" -start "test" /d"cores\sam\validation\build_gcc" /max "cd" +rem start "libvariant ADK2" /d"..\..\google\sam\variants\adk2\build_gcc" /max "cd" +rem start "libvariant SAM3X-EK" /d"..\..\atmel\sam\variants\sam3x_ek\build_gcc" /max "cd" +start "test" /d"cores\arduino\validation_usb_host\build_gcc" /max "cd" diff --git a/hardware/arduino/sam/system/USBHost/Max3421e.cpp b/hardware/arduino/sam/system/USBHost/Max3421e.cpp deleted file mode 100644 index de2f9f62a..000000000 --- a/hardware/arduino/sam/system/USBHost/Max3421e.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ -/* MAX3421E USB host controller support */ - -#include "Max3421e.h" -// #include "Max3421e_constants.h" - -static byte vbusState; - -/* Functions */ - -/* Constructor */ -MAX3421E::MAX3421E() -{ - spi_init(); -#if !defined(TARGET_MEGA_ADK) - pinMode( MAX_INT, INPUT); - pinMode( MAX_GPX, INPUT ); -#else - // "Internal" pins so can't use Arduino helper functions. - INT_DDR &= ~_BV(INT); - GPX_DDR &= ~_BV(GPX); -#endif - pinMode( MAX_SS, OUTPUT ); - digitalWrite(MAX_SS,HIGH); -#if !defined(TARGET_MEGA_ADK) - pinMode( MAX_RESET, OUTPUT ); - digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset -#else - // "Internal" pins so can't use Arduino helper functions. - RST_DDR |= _BV(RST); - RST_PORT |= _BV(RST); // Equivalent to setRST(HIGH) from old code. -#endif -} - -byte MAX3421E::getVbusState( void ) -{ - return( vbusState ); -} -/* initialization */ -//void MAX3421E::init() -//{ -// /* setup pins */ -// pinMode( MAX_INT, INPUT); -// pinMode( MAX_GPX, INPUT ); -// pinMode( MAX_SS, OUTPUT ); -// //pinMode( BPNT_0, OUTPUT ); -// //pinMode( BPNT_1, OUTPUT ); -// //digitalWrite( BPNT_0, LOW ); -// //digitalWrite( BPNT_1, LOW ); -// Deselect_MAX3421E; -// pinMode( MAX_RESET, OUTPUT ); -// digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset -//} -//byte MAX3421E::getVbusState( void ) -//{ -// return( vbusState ); -//} -//void MAX3421E::toggle( byte pin ) -//{ -// digitalWrite( pin, HIGH ); -// digitalWrite( pin, LOW ); -//} -/* Single host register write */ -void MAX3421E::regWr( byte reg, byte val) -{ - digitalWrite(MAX_SS,LOW); - SPDR = ( reg | 0x02 ); - while(!( SPSR & ( 1 << SPIF ))); - SPDR = val; - while(!( SPSR & ( 1 << SPIF ))); - digitalWrite(MAX_SS,HIGH); - return; -} -/* multiple-byte write */ -/* returns a pointer to a memory position after last written */ -char * MAX3421E::bytesWr( byte reg, byte nbytes, char * data ) -{ - digitalWrite(MAX_SS,LOW); - SPDR = ( reg | 0x02 ); - while( nbytes-- ) { - while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent - SPDR = ( *data ); // send next data byte - data++; // advance data pointer - } - while(!( SPSR & ( 1 << SPIF ))); - digitalWrite(MAX_SS,HIGH); - return( data ); -} -/* GPIO write. GPIO byte is split between 2 registers, so two writes are needed to write one byte */ -/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ -/* upper 4 bits of IOPINS1, IOPINS2 are read-only, so no masking is necessary */ -void MAX3421E::gpioWr( byte val ) -{ - regWr( rIOPINS1, val ); - val = val >>4; - regWr( rIOPINS2, val ); - - return; -} -/* Single host register read */ -byte MAX3421E::regRd( byte reg ) -{ - byte tmp; - digitalWrite(MAX_SS,LOW); - SPDR = reg; - while(!( SPSR & ( 1 << SPIF ))); - SPDR = 0; //send empty byte - while(!( SPSR & ( 1 << SPIF ))); - digitalWrite(MAX_SS,HIGH); - return( SPDR ); -} -/* multiple-bytes register read */ -/* returns a pointer to a memory position after last read */ -char * MAX3421E::bytesRd ( byte reg, byte nbytes, char * data ) -{ - digitalWrite(MAX_SS,LOW); - SPDR = reg; - while(!( SPSR & ( 1 << SPIF ))); //wait - while( nbytes ) { - SPDR = 0; //send empty byte - nbytes--; - while(!( SPSR & ( 1 << SPIF ))); - *data = SPDR; - data++; - } - digitalWrite(MAX_SS,HIGH); - return( data ); -} -/* GPIO read. See gpioWr for explanation */ -/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ -byte MAX3421E::gpioRd( void ) -{ - byte tmpbyte = 0; - tmpbyte = regRd( rIOPINS2 ); //pins 4-7 - tmpbyte &= 0xf0; //clean lower nibble - tmpbyte |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation. Upper nibble zeroes during shift, at least with this compiler - return( tmpbyte ); -} -/* reset MAX3421E using chip reset bit. SPI configuration is not affected */ -boolean MAX3421E::reset() -{ - unsigned short tmp = 0; - regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator - regWr( rUSBCTL, 0x00 ); //Remove the reset - while(!(regRd( rUSBIRQ ) & bmOSCOKIRQ )) { //wait until the PLL is stable - tmp++; //timeout after 256 attempts - if( tmp == 0 ) { - return( false ); - } - } - return( true ); -} -/* turn USB power on/off */ -/* does nothing, returns TRUE. Left for compatibility with old sketches */ -/* will be deleted eventually */ -///* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7 */ -///* OVERLOAD pin of Vbus switch is connected to GPIN7 */ -///* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high. */ -boolean MAX3421E::vbusPwr ( boolean action ) -{ -// byte tmp; -// tmp = regRd( rIOPINS2 ); //copy of IOPINS2 -// if( action ) { //turn on by setting GPOUT7 -// tmp |= bmGPOUT7; -// } -// else { //turn off by clearing GPOUT7 -// tmp &= ~bmGPOUT7; -// } -// regWr( rIOPINS2, tmp ); //send GPOUT7 -// if( action ) { -// delay( 60 ); -// } -// if (( regRd( rIOPINS2 ) & bmGPIN7 ) == 0 ) { // check if overload is present. MAX4793 /FLAG ( pin 4 ) goes low if overload -// return( false ); -// } - return( true ); // power on/off successful -} -/* probe bus to determine device presense and speed and switch host to this speed */ -void MAX3421E::busprobe( void ) -{ - byte bus_sample; - bus_sample = regRd( rHRSL ); //Get J,K status - bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte - switch( bus_sample ) { //start full-speed or low-speed host - case( bmJSTATUS ): - if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { - regWr( rMODE, MODE_FS_HOST ); //start full-speed host - vbusState = FSHOST; - } - else { - regWr( rMODE, MODE_LS_HOST); //start low-speed host - vbusState = LSHOST; - } - break; - case( bmKSTATUS ): - if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { - regWr( rMODE, MODE_LS_HOST ); //start low-speed host - vbusState = LSHOST; - } - else { - regWr( rMODE, MODE_FS_HOST ); //start full-speed host - vbusState = FSHOST; - } - break; - case( bmSE1 ): //illegal state - vbusState = SE1; - break; - case( bmSE0 ): //disconnected state - regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ); - vbusState = SE0; - break; - }//end switch( bus_sample ) -} -/* MAX3421E initialization after power-on */ -void MAX3421E::powerOn() -{ - /* Configure full-duplex SPI, interrupt pulse */ - regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL + bmGPXB )); //Full-duplex SPI, level interrupt, GPX - if( reset() == false ) { //stop/start the oscillator - Serial.println("Error: OSCOKIRQ failed to assert"); - } - - /* configure host operation */ - regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ ); // set pull-downs, Host, Separate GPIN IRQ on GPX - regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection - /* check if device is connected */ - regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus - while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish - busprobe(); //check if anything is connected - regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt - regWr( rCPUCTL, 0x01 ); //enable interrupt pin -} -/* MAX3421 state change task and interrupt handler */ -byte MAX3421E::Task( void ) -{ - byte rcode = 0; - byte pinvalue; - //Serial.print("Vbus state: "); - //Serial.println( vbusState, HEX ); - -#if !defined(TARGET_MEGA_ADK) - pinvalue = digitalRead( MAX_INT ); -#else - // "Internal" pin so can't use Arduino helper functions. - pinvalue = INT_PIN & _BV(INT) ? HIGH : LOW; // from old `readINT()` -#endif - if( pinvalue == LOW ) { - rcode = IntHandler(); - } - -#if !defined(TARGET_MEGA_ADK) - pinvalue = digitalRead( MAX_GPX ); -#else - // "Internal" pin so can't use Arduino helper functions. - pinvalue = GPX_PIN & _BV(GPX) ? HIGH : LOW; // from old `readGPX()` -#endif - if( pinvalue == LOW ) { - GpxHandler(); - } -// usbSM(); //USB state machine - return( rcode ); -} -byte MAX3421E::IntHandler() -{ - byte HIRQ; - byte HIRQ_sendback = 0x00; - HIRQ = regRd( rHIRQ ); //determine interrupt source - //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler - // HIRQ_sendback |= bmFRAMEIRQ; - //}//end FRAMEIRQ handling - if( HIRQ & bmCONDETIRQ ) { - busprobe(); - HIRQ_sendback |= bmCONDETIRQ; - } - /* End HIRQ interrupts handling, clear serviced IRQs */ - regWr( rHIRQ, HIRQ_sendback ); - return( HIRQ_sendback ); -} -byte MAX3421E::GpxHandler() -{ - byte GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register -// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload -// vbusPwr( OFF ); //attempt powercycle -// delay( 1000 ); -// vbusPwr( ON ); -// regWr( rGPINIRQ, bmGPINIRQ7 ); -// } - return( GPINIRQ ); -} - -//void MAX3421E::usbSM( void ) //USB state machine -//{ -// -// -//} diff --git a/hardware/arduino/sam/system/USBHost/Max3421e.h b/hardware/arduino/sam/system/USBHost/Max3421e.h deleted file mode 100644 index 1aef86964..000000000 --- a/hardware/arduino/sam/system/USBHost/Max3421e.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ -/* MAX3421E functions */ -#ifndef _MAX3421E_H_ -#define _MAX3421E_H_ - - -//#include -//#include -#include "Arduino.h" -#include "Max3421e_constants.h" - -class MAX3421E /* : public SPI */ { - // byte vbusState; - public: - MAX3421E( void ); - byte getVbusState( void ); -// void toggle( byte pin ); - static void regWr( byte, byte ); - char * bytesWr( byte, byte, char * ); - static void gpioWr( byte ); - byte regRd( byte ); - char * bytesRd( byte, byte, char * ); - byte gpioRd( void ); - boolean reset(); - boolean vbusPwr ( boolean ); - void busprobe( void ); - void powerOn(); - byte IntHandler(); - byte GpxHandler(); - byte Task(); - private: - static void spi_init() { - uint8_t tmp; - // initialize SPI pins - pinMode(SCK_PIN, OUTPUT); - pinMode(MOSI_PIN, OUTPUT); - pinMode(MISO_PIN, INPUT); - pinMode(SS_PIN, OUTPUT); - digitalWrite( SS_PIN, HIGH ); - /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ - SPCR = 0x50; - SPSR = 0x01; - /**/ - tmp = SPSR; - tmp = SPDR; - } -// void init(); - friend class Max_LCD; -}; - - - - -#endif //_MAX3421E_H_ diff --git a/hardware/arduino/sam/system/USBHost/Max3421e_constants.h b/hardware/arduino/sam/system/USBHost/Max3421e_constants.h deleted file mode 100644 index 600e2ba0e..000000000 --- a/hardware/arduino/sam/system/USBHost/Max3421e_constants.h +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ -/* MAX3421E register/bit names and bitmasks */ - -#ifndef _MAX3421Econstants_h_ -#define _MAX3421Econstants_h_ - -/* SPI pins for diffrent Arduinos */ - -#define MEGA256_IS_ADK // Undefine this if you're using a non-ADK Mega256 - -// TODO: Check if the 2560 check should use `defined` too. -#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) - #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 -#if defined(__AVR_ATmega2560__) && defined(MEGA256_IS_ADK) - #define TARGET_MEGA_ADK - #define SS_PIN 53 // TODO: Handle this as an internal pin. -#else - // TODO: Test with Mega + shield combination - #define SS_PIN 53 -#endif -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - #define SCK_PIN 13 - #define MISO_PIN 12 - #define MOSI_PIN 11 - #define SS_PIN 10 -#else - #error The currently selected board needs to have its SPI pin definitions added to this file. -#endif - -#if !defined(TARGET_MEGA_ADK) - #define MAX_SS SS_PIN - #define MAX_INT 9 - #define MAX_GPX 8 - #define MAX_RESET 7 -#else - // Because the Arduino Mega ADK board uses "internal" pins (i.e. ones that - // are not broken out to headers, are not in `pins_arduino.h` and can't - // be used with functions like `pinMode()` & `digitalWrite()`) they need - // to be defined by the low-level AVR approach. - // These definitions and the code to use them comes from an older version - // of the `Max3421e.cpp` file. - // TODO: Add these internal pins to `pins_arduino.h` for the Mega ADK so - // we can usual the standard Arduino functions & not special-case this? - #define INT PE6 - #define INT_PORT PORTE - #define INT_DDR DDRE - #define INT_PIN PINE - - #define RST PJ2 - #define RST_PORT PORTJ - #define RST_DDR DDRJ - #define RST_PIN PINJ - - #define GPX PJ3 - #define GPX_PORT PORTJ - #define GPX_DDR DDRJ - #define GPX_PIN PINJ - - #define MAX_SS SS_PIN // TODO: Handle this as an internal pin. -#endif - -/* "Breakpoint" pins for debugging */ -//#define BPNT_0 3 -//#define BPNT_1 2 - -//#define Select_MAX3421E digitalWrite(MAX_SS,LOW) -//#define Deselect_MAX3421E digitalWrite(MAX_SS,HIGH) - -/* */ - -#define ON true -#define OFF false - -/* VBUS states */ -#define SE0 0 -#define SE1 1 -#define FSHOST 2 -#define LSHOST 3 - -/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ -// -// MAX3421E Registers in HOST mode. -// -#define rRCVFIFO 0x08 //1<<3 -#define rSNDFIFO 0x10 //2<<3 -#define rSUDFIFO 0x20 //4<<3 -#define rRCVBC 0x30 //6<<3 -#define rSNDBC 0x38 //7<<3 - -#define rUSBIRQ 0x68 //13<<3 -/* USBIRQ Bits */ -#define bmVBUSIRQ 0x40 //b6 -#define bmNOVBUSIRQ 0x20 //b5 -#define bmOSCOKIRQ 0x01 //b0 - -#define rUSBIEN 0x70 //14<<3 -/* USBIEN Bits */ -#define bmVBUSIE 0x40 //b6 -#define bmNOVBUSIE 0x20 //b5 -#define bmOSCOKIE 0x01 //b0 - -#define rUSBCTL 0x78 //15<<3 -/* USBCTL Bits */ -#define bmCHIPRES 0x20 //b5 -#define bmPWRDOWN 0x10 //b4 - -#define rCPUCTL 0x80 //16<<3 -/* CPUCTL Bits */ -#define bmPUSLEWID1 0x80 //b7 -#define bmPULSEWID0 0x40 //b6 -#define bmIE 0x01 //b0 - -#define rPINCTL 0x88 //17<<3 -/* PINCTL Bits */ -#define bmFDUPSPI 0x10 //b4 -#define bmINTLEVEL 0x08 //b3 -#define bmPOSINT 0x04 //b2 -#define bmGPXB 0x02 //b1 -#define bmGPXA 0x01 //b0 -// GPX pin selections -#define GPX_OPERATE 0x00 -#define GPX_VBDET 0x01 -#define GPX_BUSACT 0x02 -#define GPX_SOF 0x03 - -#define rREVISION 0x90 //18<<3 - -#define rIOPINS1 0xa0 //20<<3 - -/* IOPINS1 Bits */ -#define bmGPOUT0 0x01 -#define bmGPOUT1 0x02 -#define bmGPOUT2 0x04 -#define bmGPOUT3 0x08 -#define bmGPIN0 0x10 -#define bmGPIN1 0x20 -#define bmGPIN2 0x40 -#define bmGPIN3 0x80 - -#define rIOPINS2 0xa8 //21<<3 -/* IOPINS2 Bits */ -#define bmGPOUT4 0x01 -#define bmGPOUT5 0x02 -#define bmGPOUT6 0x04 -#define bmGPOUT7 0x08 -#define bmGPIN4 0x10 -#define bmGPIN5 0x20 -#define bmGPIN6 0x40 -#define bmGPIN7 0x80 - -#define rGPINIRQ 0xb0 //22<<3 -/* GPINIRQ Bits */ -#define bmGPINIRQ0 0x01 -#define bmGPINIRQ1 0x02 -#define bmGPINIRQ2 0x04 -#define bmGPINIRQ3 0x08 -#define bmGPINIRQ4 0x10 -#define bmGPINIRQ5 0x20 -#define bmGPINIRQ6 0x40 -#define bmGPINIRQ7 0x80 - -#define rGPINIEN 0xb8 //23<<3 -/* GPINIEN Bits */ -#define bmGPINIEN0 0x01 -#define bmGPINIEN1 0x02 -#define bmGPINIEN2 0x04 -#define bmGPINIEN3 0x08 -#define bmGPINIEN4 0x10 -#define bmGPINIEN5 0x20 -#define bmGPINIEN6 0x40 -#define bmGPINIEN7 0x80 - -#define rGPINPOL 0xc0 //24<<3 -/* GPINPOL Bits */ -#define bmGPINPOL0 0x01 -#define bmGPINPOL1 0x02 -#define bmGPINPOL2 0x04 -#define bmGPINPOL3 0x08 -#define bmGPINPOL4 0x10 -#define bmGPINPOL5 0x20 -#define bmGPINPOL6 0x40 -#define bmGPINPOL7 0x80 - -#define rHIRQ 0xc8 //25<<3 -/* HIRQ Bits */ -#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume -#define bmRWUIRQ 0x02 -#define bmRCVDAVIRQ 0x04 -#define bmSNDBAVIRQ 0x08 -#define bmSUSDNIRQ 0x10 -#define bmCONDETIRQ 0x20 -#define bmFRAMEIRQ 0x40 -#define bmHXFRDNIRQ 0x80 - -#define rHIEN 0xd0 //26<<3 -/* HIEN Bits */ -#define bmBUSEVENTIE 0x01 -#define bmRWUIE 0x02 -#define bmRCVDAVIE 0x04 -#define bmSNDBAVIE 0x08 -#define bmSUSDNIE 0x10 -#define bmCONDETIE 0x20 -#define bmFRAMEIE 0x40 -#define bmHXFRDNIE 0x80 - -#define rMODE 0xd8 //27<<3 -/* MODE Bits */ -#define bmHOST 0x01 -#define bmLOWSPEED 0x02 -#define bmHUBPRE 0x04 -#define bmSOFKAENAB 0x08 -#define bmSEPIRQ 0x10 -#define bmDELAYISO 0x20 -#define bmDMPULLDN 0x40 -#define bmDPPULLDN 0x80 - -#define rPERADDR 0xe0 //28<<3 - -#define rHCTL 0xe8 //29<<3 -/* HCTL Bits */ -#define bmBUSRST 0x01 -#define bmFRMRST 0x02 -#define bmSAMPLEBUS 0x04 -#define bmSIGRSM 0x08 -#define bmRCVTOG0 0x10 -#define bmRCVTOG1 0x20 -#define bmSNDTOG0 0x40 -#define bmSNDTOG1 0x80 - -#define rHXFR 0xf0 //30<<3 -/* Host transfer token values for writing the HXFR register (R30) */ -/* OR this bit field with the endpoint number in bits 3:0 */ -#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 -#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 -#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 -#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 -#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 -#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 -#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 - -#define rHRSL 0xf8 //31<<3 -/* HRSL Bits */ -#define bmRCVTOGRD 0x10 -#define bmSNDTOGRD 0x20 -#define bmKSTATUS 0x40 -#define bmJSTATUS 0x80 -#define bmSE0 0x00 //SE0 - disconnect state -#define bmSE1 0xc0 //SE1 - illegal state -/* Host error result codes, the 4 LSB's in the HRSL register */ -#define hrSUCCESS 0x00 -#define hrBUSY 0x01 -#define hrBADREQ 0x02 -#define hrUNDEF 0x03 -#define hrNAK 0x04 -#define hrSTALL 0x05 -#define hrTOGERR 0x06 -#define hrWRONGPID 0x07 -#define hrBADBC 0x08 -#define hrPIDERR 0x09 -#define hrPKTERR 0x0A -#define hrCRCERR 0x0B -#define hrKERR 0x0C -#define hrJERR 0x0D -#define hrTIMEOUT 0x0E -#define hrBABBLE 0x0F - -#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) -#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) - - -#endif //_MAX3421Econstants_h_ diff --git a/hardware/arduino/sam/system/USBHost/Usb.cpp b/hardware/arduino/sam/system/USBHost/Usb.cpp index d312acaa4..19d50ba3f 100644 --- a/hardware/arduino/sam/system/USBHost/Usb.cpp +++ b/hardware/arduino/sam/system/USBHost/Usb.cpp @@ -1,431 +1,712 @@ /* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ /* USB functions */ + +#include "Arduino.h" #include "Usb.h" +#include -static byte usb_error = 0; -static byte usb_task_state; -DEV_RECORD devtable[ USB_NUMDEVICES + 1 ]; -EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device +//#define TRACE_USBHOST(x) x +#define TRACE_USBHOST(x) +static uint32_t usb_error = 0; +static uint32_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; -/* constructor */ +DEV_RECORD devtable[USB_NUMDEVICES + 1]; -USB::USB () { - usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine - init(); +// Endpoint data structure used during enumeration for uninitialized device. +EP_RECORD dev0ep; + +/** + * Class Constructor. + */ +USBHost::USBHost () { + // Set up state machine + usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; + + // Init host stack + init(); } -/* Initialize data structures */ -void USB::init() + +/** + * Initialize data structures. + */ +void USBHost::init() { - byte i; - for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) { - devtable[ i ].epinfo = NULL; //clear device table - devtable[ i ].devclass = 0; - } - devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device - // not necessary dev0ep.MaxPktSize = 8; //minimum possible - dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 + + uint8_t i = 0; + + for (i = 0; i < (USB_NUMDEVICES + 1); i++) + { + // Clear device table + devtable[i].epinfo = 0; + devtable[i].devclass = 0; + } + + // Set single EP for uninitialized device + devtable[0].epinfo = &dev0ep; + /* dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 dev0ep.rcvToggle = bmRCVTOG0; +*/ } -byte USB::getUsbTaskState( void ) + +/** + * Get USB state. + */ +uint32_t USBHost::getUsbTaskState(void) { - return( usb_task_state ); + return (usb_task_state); } -void USB::setUsbTaskState( byte state ) + +/** + * Set USB state. + */ +void USBHost::setUsbTaskState(uint32_t state) { usb_task_state = state; -} -EP_RECORD* USB::getDevTableEntry( byte addr, byte ep ) -{ - EP_RECORD* ptr; - ptr = devtable[ addr ].epinfo; - ptr += ep; - return( ptr ); -} -/* set device table entry */ -/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ -void USB::setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr ) -{ - devtable[ addr ].epinfo = eprecord_ptr; - //return(); -} -/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */ -/* depending on request. Actual requests are defined as inlines */ -/* return codes: */ -/* 00 = success */ -/* 01-0f = non-zero HRSLT */ -byte USB::ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) -{ - boolean direction = false; //request direction, IN or OUT - byte rcode; - SETUP_PKT setup_pkt; - - regWr( rPERADDR, addr ); //set peripheral address - if( bmReqType & 0x80 ) { - direction = true; //determine request direction - } - /* fill in setup packet */ - setup_pkt.ReqType_u.bmRequestType = bmReqType; - setup_pkt.bRequest = bRequest; - setup_pkt.wVal_u.wValueLo = wValLo; - setup_pkt.wVal_u.wValueHi = wValHi; - setup_pkt.wIndex = wInd; - setup_pkt.wLength = nbytes; - bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt ); //transfer to setup packet FIFO - rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet - //Serial.println("Setup packet"); //DEBUG - if( rcode ) { //return HRSLT if not zero - Serial.print("Setup packet error: "); - Serial.print( rcode, HEX ); - return( rcode ); - } - //Serial.println( direction, HEX ); - if( dataptr != NULL ) { //data stage, if present - rcode = ctrlData( addr, ep, nbytes, dataptr, direction ); - } - if( rcode ) { //return error - Serial.print("Data packet error: "); - Serial.print( rcode, HEX ); - return( rcode ); - } - rcode = ctrlStatus( ep, direction ); //status stage - return( rcode ); -} -/* Control transfer with status stage and no data stage */ -/* Assumed peripheral address is already set */ -byte USB::ctrlStatus( byte ep, boolean direction, unsigned int nak_limit ) -{ - byte rcode; - if( direction ) { //GET - rcode = dispatchPkt( tokOUTHS, ep, nak_limit ); - } - else { - rcode = dispatchPkt( tokINHS, ep, nak_limit ); - } - return( rcode ); -} -/* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */ -byte USB::ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit ) -{ - byte rcode; - if( direction ) { //IN transfer - devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1; - rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit ); - return( rcode ); - } - else { //OUT transfer - devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1; - rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit ); - return( rcode ); - } -} -/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ -/* Keep sending INs and writes data to memory area pointed by 'data' */ -/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, - fe USB xfer timeout */ -byte USB::inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit ) -{ - byte rcode; - byte pktsize; - byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; - unsigned int xfrlen = 0; - regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value - while( 1 ) { // use a 'return' to exit this loop - rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. - if( rcode ) { - return( rcode ); //should be 0, indicating ACK. Else return error code. - } - /* check for RCVDAVIRQ and generate error if not present */ - /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ - if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { - return ( 0xf0 ); //receive error - } - pktsize = regRd( rRCVBC ); //number of received bytes - data = bytesRd( rRCVFIFO, pktsize, data ); - regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - xfrlen += pktsize; // add this packet's byte count to total transfer length - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes? - if( regRd( rHRSL ) & bmRCVTOGRD ) { //save toggle value - devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1; - } - else { - devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0; - } - return( 0 ); - } - }//while( 1 ) } -/* Google variant of inTransfer. Pasted verbatim from ADK. Returns length instead of error code. Provided for compatibility with Google Open Accessory code */ -int USB::newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit ) +/** + * Get device table entry. + */ +EP_RECORD* USBHost::getDevTableEntry(uint32_t addr, uint32_t ep) { - byte rcode; - byte pktsize; - byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; - unsigned int xfrlen = 0; - regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value - while( 1 ) { // use a 'return' to exit this loop - rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. - if( rcode ) { - return -1; //should be 0, indicating ACK. Else return error code. - } - /* check for RCVDAVIRQ and generate error if not present */ - /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ - if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { - return -1; //receive error - } - pktsize = regRd( rRCVBC ); //number of received bytes - if (xfrlen+pktsize <= nbytes) { - // Only copy the data to the buffer if the buffer's large enough. - data = bytesRd( rRCVFIFO, pktsize, data ); + EP_RECORD* ptr = 0; + + ptr = devtable[addr].epinfo; + ptr += ep; + return ptr; +} + +/** + * Set device table entry. + */ +void USBHost::setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr) +{ + devtable[addr].epinfo = eprecord_ptr; +} + +/** + * Send a control request. + * Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer depending on request. + * Actual requests are defined as inlines. + * + * return codes: + * 00 = success + * 01-0f = non-zero HRSLT + */ +uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) +{ + // Request direction, IN or OUT + uint32_t direction = 0; + uint32_t rcode = 0; + SETUP_PKT setup_pkt; + + TRACE_USBHOST(printf(" => ctrlReq\r\n");) + + // Set peripheral address + //regWr(rPERADDR, addr); + + // Allocate EP0 with default 8 bytes size if not already initialized + rcode = UHD_EP0_Alloc(0, 8); + if (rcode) + { + TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : EP0 allocation error: %lu\r\n", rcode);) + return (rcode); } - regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - xfrlen += pktsize; // add this packet's byte count to total transfer length - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes? - if( regRd( rHRSL ) & bmRCVTOGRD ) { //save toggle value - devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1; + + // Determine request direction + if (bmReqType & 0x80) + { + direction = 1; + } + + // Fill in setup packet + setup_pkt.ReqType_u.bmRequestType = bmReqType; + setup_pkt.bRequest = bRequest; + setup_pkt.wVal_u.wValueLo = wValLo; + setup_pkt.wVal_u.wValueHi = wValHi; + setup_pkt.wIndex = wInd; + setup_pkt.wLength = nbytes; + + // Transfer to setup packet FIFO + //bytesWr(rSUDFIFO, 8, (uint8_t *)&setup_pkt); + UHD_EP_Write(ep, 8, (uint8_t *)&setup_pkt); + + // Dispatch packet + rcode = dispatchPkt(tokSETUP, ep, nak_limit); + if (rcode) + { + // Return HRSLT if not zero + TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : Setup packet error: %lu\r\n", rcode);) + return (rcode); + } + + // Data stage (if present) + if (dataptr != 0) + { + rcode = ctrlData(addr, ep, nbytes, dataptr, direction); + if (rcode) + { + TRACE_USBHOST(printf("/!\\ USBHost::ctrlData : Data packet error: %lu\r\n", rcode);) + return (rcode); + } + } + + // Status stage + rcode = ctrlStatus(ep, direction); + return (rcode); + +} + +/** + * Control transfer with status stage and no data stage. + * Assumes peripheral address is already set. + */ +uint32_t USBHost::ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit) +{ + uint32_t rcode = 0; + + if (direction) + { + // GET + TRACE_USBHOST(printf(" => ctrlStatus OUTHS\r\n");) + rcode = dispatchPkt(tokOUTHS, ep, nak_limit); + } + else + { + // SET + TRACE_USBHOST(printf(" => ctrlStatus INHS\r\n");) + rcode = dispatchPkt(tokINHS, ep, nak_limit); + } + + return (rcode); +} + +/** + * Control transfer with data stage. Stages 2 and 3 of control transfer. + * Assumes peripheral address is set and setup packet has been sent. + */ +uint32_t USBHost::ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction, uint32_t nak_limit) +{ + uint32_t rcode = 0; + + if (direction) + { + // IN transfer + //devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG1; + TRACE_USBHOST(printf(" => ctrlData IN\r\n");) + rcode = inTransfer(addr, ep, nbytes, dataptr, nak_limit); + return (rcode); + } + else + { + // OUT transfer + //devtable[addr].epinfo[ep].sndToggle = bmSNDTOG1; + TRACE_USBHOST(printf(" => ctrlData OUT\r\n");) + rcode = outTransfer(addr, ep, nbytes, dataptr, nak_limit); + return (rcode); + } +} + +/** + * IN transfer to arbitrary endpoint. + * Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. + * Keep sending INs and writes data to memory area pointed by 'data'. + * rcode 0 if no errors + * 01-0f is relayed from dispatchPkt() + * f0 means RCVDAVIRQ error + * fe USB xfer timeout + */ +uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) +{ + uint32_t rcode = 0; + uint32_t pktsize = 0; + uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; + uint32_t xfrlen = 0; + + // Set toggle value + //regWr(rHCTL, devtable[addr].epinfo[ep].rcvToggle); + + while (1) + { + // Use a 'return' to exit this loop + // IN packet to EP-'endpoint'. Function takes care of NAKS. + rcode = dispatchPkt(tokIN, ep, nak_limit); + if (rcode) + { + // Should be 0, indicating ACK. Else return error code. + return (rcode); + } + + // check for RCVDAVIRQ and generate error if not present + // the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that + /*if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) + { + // Receive error + return (0xf0); + }*/ + + // Number of received bytes + //pktsize = regRd(rRCVBC); + //data = bytesRd(rRCVFIFO, pktsize, data); + pktsize = uhd_byte_count(ep); + if (nbytes < pktsize) + printf("ce test n'a pas ete fait...\r\n"); + data += UHD_EP_Read(ep, pktsize, data); + + // Clear the IRQ & free the buffer + //regWr(rHIRQ, bmRCVDAVIRQ); + + // Add this packet's byte count to total transfer length + xfrlen += pktsize; + + // The transfer is complete under two conditions: + // 1. The device sent a short packet (L.T. maxPacketSize) + // 2. 'nbytes' have been transferred. + if ((pktsize < maxpktsize) || (xfrlen >= nbytes)) + { + /*// Have we transferred 'nbytes' bytes? + if (regRd(rHRSL) & bmRCVTOGRD) + { + // Save toggle value + devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG1; } - else { - devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0; + else + { + devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG0; + }*/ + + return (0); + } + } +} + +/** + * Google variant of inTransfer. + * Pasted verbatim from ADK. Returns length instead of error code. + * Provided for compatibility with Google Open Accessory code. + */ +int32_t USBHost::newInTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) +{ +/* + uint32_t rcode = 0; + uint32_t pktsize = 0; + uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; + uint32_t xfrlen = 0; + + // Set toggle value + regWr(rHCTL, devtable[addr].epinfo[ep].rcvToggle); + + while (1) + { + // Use a 'return' to exit this loop + // IN packet to EP-'endpoint'. Function takes care of NAKS. + rcode = dispatchPkt(tokIN, ep, nak_limit); + if (rcode) + { + // Should be 0, indicating ACK. Else return error code. + return -1; + } + + // check for RCVDAVIRQ and generate error if not present + // the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that + if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) + { + // Receive error + return -1; + } + + // Number of received bytes + pktsize = regRd(rRCVBC); + + if (xfrlen + pktsize <= nbytes) + { + // Only copy the data to the buffer if the buffer's large enough. + data = bytesRd(rRCVFIFO, pktsize, data); + } + + // Clear the IRQ & free the buffer + regWr(rHIRQ, bmRCVDAVIRQ); + + // Add this packet's byte count to total transfer length + xfrlen += pktsize; + + // The transfer is complete under two conditions: + // 1. The device sent a short packet (L.T. maxPacketSize) + // 2. 'nbytes' have been transferred. + if ((pktsize < maxpktsize) || (xfrlen >= nbytes)) + { + // Have we transferred 'nbytes' bytes? + if (regRd(rHRSL) & bmRCVTOGRD) + { + // Save toggle value + devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG1; } - if (xfrlen <= nbytes) { - return xfrlen; - } else { - // Buffer overflow avoided so treat it as an error rather - // than return partial data. - return -1; - } + else + { + devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG0; + } + + if (xfrlen <= nbytes) + { + return xfrlen; + } + else + { + // Buffer overflow avoided so treat it as an error rather + // than return partial data. + return -1; + } } - }//while( 1 ) + } +*/ +printf("error2\r\n"); +return 1; } -/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ -/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ -/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ -/* major part of this function borrowed from code shared by Richard Ibbotson */ -byte USB::outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit ) +/** + * OUT transfer to arbitrary endpoint. + * Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. + * Handles NAK bug per Maxim Application Note 4000 for single buffer transfer + * rcode 0 if no errors + * 01-0f is relayed from HRSL + * + * Major part of this function borrowed from code shared by Richard Ibbotson + */ +uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) { - byte rcode, retry_count; - char* data_p = data; //local copy of the data pointer - unsigned int bytes_tosend, nak_count; - unsigned int bytes_left = nbytes; - byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - - if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64 - return 0xFE; - } - - regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle ); //set toggle value - while( bytes_left ) { - retry_count = 0; - nak_count = 0; - bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left; - bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO - regWr( rSNDBC, bytes_tosend ); //set number of bytes - regWr( rHXFR, ( tokOUT | ep )); //dispatch packet - while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ - regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ - rcode = ( regRd( rHRSL ) & 0x0f ); - while( rcode && ( timeout > millis())) { - switch( rcode ) { - case hrNAK: - nak_count++; - if( nak_limit && ( nak_count == USB_NAK_LIMIT )) { - return( rcode); //return NAK - } - break; - case hrTIMEOUT: - retry_count++; - if( retry_count == USB_RETRY_LIMIT ) { - return( rcode ); //return TIMEOUT - } - break; - default: - return( rcode ); - }//switch( rcode... - /* process NAK according to Host out NAK bug */ - regWr( rSNDBC, 0 ); - regWr( rSNDFIFO, *data_p ); - regWr( rSNDBC, bytes_tosend ); - regWr( rHXFR, ( tokOUT | ep )); //dispatch packet - while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ - regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ - rcode = ( regRd( rHRSL ) & 0x0f ); - }//while( rcode && .... - bytes_left -= bytes_tosend; - data_p += bytes_tosend; - }//while( bytes_left... - devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle - return( rcode ); //should be 0 in all cases -} -/* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ -/* If NAK, tries to re-send up to nak_limit times */ -/* If nak_limit == 0, do not count NAKs, exit after timeout */ -/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ -/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ -byte USB::dispatchPkt( byte token, byte ep, unsigned int nak_limit ) -{ - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - byte tmpdata; - byte rcode; - unsigned int nak_count = 0; - char retry_count = 0; +/* + uint32_t rcode, retry_count; + uint8_t* data_p = data; + uint32_t bytes_tosend, nak_count; + uint32_t bytes_left = nbytes; + uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; + uint32_t timeout = millis() + USB_XFER_TIMEOUT; - while( timeout > millis() ) { - regWr( rHXFR, ( token|ep )); //launch the transfer - rcode = 0xff; - while( millis() < timeout ) { //wait for transfer completion - tmpdata = regRd( rHIRQ ); - if( tmpdata & bmHXFRDNIRQ ) { - regWr( rHIRQ, bmHXFRDNIRQ ); //clear the interrupt - rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ - }//while ( millis() < timeout - if( rcode != 0x00 ) { //exit if timeout - return( rcode ); - } - rcode = ( regRd( rHRSL ) & 0x0f ); //analyze transfer result - switch( rcode ) { - case hrNAK: - nak_count ++; - if( nak_limit && ( nak_count == nak_limit )) { - return( rcode ); - } - break; - case hrTIMEOUT: - retry_count ++; - if( retry_count == USB_RETRY_LIMIT ) { - return( rcode ); - } - break; - default: - return( rcode ); - }//switch( rcode - }//while( timeout > millis() - return( rcode ); -} -/* USB main task. Performs enumeration/cleanup */ -void USB::Task( void ) //USB state machine -{ - byte i; - byte rcode; - static byte tmpaddr; - byte tmpdata; - static unsigned long delay = 0; - USB_DEVICE_DESCRIPTOR buf; - /**/ - tmpdata = getVbusState(); -// Serial.print("vbusState: "); -// Serial.print(tmpdata, HEX); -// -// Serial.print("\n"); - /**/ - /* modify USB task state if Vbus changed */ + if (!maxpktsize) + { + // Todo: move this check close to epinfo init. Make it 1< pktsize <64 + return 0xFE; + } - switch( tmpdata ) { - case SE1: //illegal state + // Set toggle value + regWr(rHCTL, devtable[addr].epinfo[ep].sndToggle); + + while (bytes_left) + { + retry_count = 0; + nak_count = 0; + bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; + + // Fill output FIFO + bytesWr(rSNDFIFO, bytes_tosend, data_p); + // Set number of bytes + regWr(rSNDBC, bytes_tosend); + + // Dispatch packet + regWr(rHXFR, (tokOUT | ep)); + + // Wait for the completion IRQ + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) + ; + + // Clear IRQ + regWr(rHIRQ, bmHXFRDNIRQ); + rcode = (regRd(rHRSL) & 0x0f); + + while (rcode && (timeout > millis())) + { + switch (rcode) + { + case hrNAK: + nak_count++; + if (nak_limit && (nak_count == USB_NAK_LIMIT)) { + return (rcode); + } + break; + case hrTIMEOUT: + retry_count++; + if (retry_count == USB_RETRY_LIMIT) { + return (rcode); + } + break; + default: + return (rcode); + } + + // Process NAK according to Host out NAK bug + regWr(rSNDBC, 0); + regWr(rSNDFIFO, *data_p); + regWr(rSNDBC, bytes_tosend); + + // Dispatch packet + regWr(rHXFR, (tokOUT | ep)); + + // Wait for the completion IRQ + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) + ; + + // Clear IRQ + regWr(rHIRQ, bmHXFRDNIRQ); + rcode = (regRd(rHRSL) & 0x0f); + } + + bytes_left -= bytes_tosend; + data_p += bytes_tosend; + } + + // Update toggle + devtable[ addr ].epinfo[ ep ].sndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? bmSNDTOG1 : bmSNDTOG0; + return (rcode); +*/ +printf("error3\r\n"); +return 1; + +} + +/** + * Dispatch USB packet. + * Assumes peripheral address is set and relevant buffer is loaded/empty. + * If NAK, tries to re-send up to nak_limit times. + * If nak_limit == 0, do not count NAKs, exit after timeout. + * If bus timeout, re-sends up to USB_RETRY_LIMIT times. + * rcode 0 for success + * 1 for naked + * 2 for timeout + */ +uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit) +{ + uint32_t timeout = millis() + USB_XFER_TIMEOUT; + uint32_t nak_count = 0; + + TRACE_USBHOST(printf(" => dispatchPkt token=%lu\r\n", token);) + + // Launch the transfer + //regWr(rHXFR, (token | ep)); + UHD_EP_Send(ep, token); + + while (timeout > millis()) + { + // Wait for transfer completion + if (UHD_EP_Is_Transfer_Complete(ep, token)) + { + return 0; + } + + // + if (Is_uhd_nak_received(ep)) + { + uhd_ack_nak_received(ep); + nak_count++; + if (nak_limit && (nak_count == nak_limit)) + { + return 1; + } + } + } + + return 2; +} + +/** + * USB main task. + * Performs enumeration/cleanup. + */ +void USBHost::Task(void) +{ + uint32_t i = 0; + uint32_t rcode = 0; + //static uint8_t tmpaddr = 0; + volatile uint32_t tmpdata = 0; + static uint32_t delay = 0; + USB_DEVICE_DESCRIPTOR buf; + + // Update USB task state on Vbus change + tmpdata = UHD_GetVBUSState(); + switch (tmpdata) + { + case UHD_STATE_ERROR: + // Illegal state usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; break; - case SE0: //disconnected - if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) { + + case UHD_STATE_DISCONNECTED: + // Disconnected state + if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) + { usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; } break; - case FSHOST: //attached - case LSHOST: - if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) { + + case UHD_STATE_CONNECTED: + // Attached state + if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) + { delay = millis() + USB_SETTLE_DELAY; usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; } break; - }// switch( tmpdata - //Serial.print("USB task state: "); - //Serial.println( usb_task_state, HEX ); - switch( usb_task_state ) { + } + + // USB state machine + switch (usb_task_state) + { case USB_DETACHED_SUBSTATE_INITIALIZE: + TRACE_USBHOST(printf(" + USB_DETACHED_SUBSTATE_INITIALIZE\r\n");) + + // Init USB stack and driver + UHD_Init(); init(); + usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; break; - case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here + + case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: + // Nothing to do break; - case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here + + case USB_DETACHED_SUBSTATE_ILLEGAL: + // Nothing to do break; - case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device - if( delay < millis() ) { + + case USB_ATTACHED_SUBSTATE_SETTLE: + // Settle time for just attached device + if (delay < millis()) + { + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_SETTLE\r\n");) usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; } break; + case USB_ATTACHED_SUBSTATE_RESET_DEVICE: - regWr( rHCTL, bmBUSRST ); //issue bus reset + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_RESET_DEVICE\r\n");) + + // Trigger Bus Reset + UHD_BusReset(); usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; break; + case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: - if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) { - tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation - regWr( rMODE, tmpdata ); -// regWr( rMODE, bmSOFKAENAB ); + if (Is_uhd_reset_sent()) + { + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE\r\n");) + + // Clear Bus Reset flag + uhd_ack_reset_sent(); + + // Enable Start Of Frame generation + uhd_enable_sof(); + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; - delay = millis() + 20; //20ms wait after reset per USB spec + + // Wait 20ms after Bus Reset (USB spec) + delay = millis() + 20; } break; - case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order - if( regRd( rHIRQ ) & bmFRAMEIRQ ) { //when first SOF received we can continue - if( delay < millis() ) { //20ms passed - usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; - } + + case USB_ATTACHED_SUBSTATE_WAIT_SOF: + // Wait for SOF received first + if (Is_uhd_sof()) + { + if (delay < millis()) + { + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_SOF\r\n");) + + // 20ms waiting elapsed + usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; + } } break; + case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE: - // toggle( BPNT_0 ); - devtable[ 0 ].epinfo->MaxPktSize = 8; //set max.packet size to min.allowed - rcode = getDevDescr( 0, 0, 8, ( char* )&buf ); - if( rcode == 0 ) { - devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0; - usb_task_state = USB_STATE_ADDRESSING; + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE\r\n");) + + // Get Device descriptor size + // Set max.packet size to the minimum allowed + devtable[0].epinfo->MaxPktSize = 8; + rcode = getDevDescr(0, 0, 8, (uint8_t*)&buf); + if (rcode == 0) + { + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE : max pkt size = %d\r\n", buf.bMaxPacketSize0);) + devtable[0].epinfo->MaxPktSize = buf.bMaxPacketSize0; + + // Reconfigure EP0 with max pkt size. (should be done after a USB reset) + UHD_EP_Free(0, 0); + if (UHD_EP0_Alloc(0, devtable[0].epinfo->MaxPktSize) == 0) + { + usb_task_state = USB_STATE_ADDRESSING; + } + else + { + TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE : realloc failure!\r\n");) + usb_task_state = USB_STATE_ERROR; + } } - else { + else + { usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; usb_task_state = USB_STATE_ERROR; } break; + case USB_STATE_ADDRESSING: - for( i = 1; i < USB_NUMDEVICES; i++ ) { - if( devtable[ i ].epinfo == NULL ) { - devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize - //temporary record - //until plugged with real device endpoint structure - rcode = setAddr( 0, 0, i ); - if( rcode == 0 ) { - tmpaddr = i; - usb_task_state = USB_STATE_CONFIGURING; + for (i = 1; i < USB_NUMDEVICES; i++) + { + TRACE_USBHOST(printf(" + USB_STATE_ADDRESSING (i=%lu)\r\n", i);) + + if (devtable[i].epinfo == 0) + { + // Set correct MaxPktSize + // Temporary record until plugged with real device endpoint structure + devtable[i].epinfo = devtable[0].epinfo; + + rcode = setAddr(0, 0, i); + if (rcode == 0) + { + // Free address 0 used to start enumeration + UHD_EP_Free(0, 0); + + // Alloc control endpoint with the new USB address + if (UHD_EP0_Alloc(i, devtable[i].epinfo->MaxPktSize) == 0) + { + usb_task_state = USB_STATE_CONFIGURING; + TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING (i=%lu)\r\n", i);) + } + else + { + // Set address error + TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING (i=%lu) : realloc failure!\r\n", i);) + usb_error = USB_STATE_ADDRESSING; + usb_task_state = USB_STATE_ERROR; + } } - else { - usb_error = USB_STATE_ADDRESSING; //set address error + else + { + // Set address error + usb_error = USB_STATE_ADDRESSING; usb_task_state = USB_STATE_ERROR; } - break; //break if address assigned or error occured during address assignment attempt + // Break if address assigned or error occured during address assignment attempt + break; } - }//for( i = 1; i < USB_NUMDEVICES; i++ - if( usb_task_state == USB_STATE_ADDRESSING ) { //no vacant place in devtable + } + + if (usb_task_state == USB_STATE_ADDRESSING) + { + // No vacant place in devtable usb_error = 0xfe; usb_task_state = USB_STATE_ERROR; } break; + case USB_STATE_CONFIGURING: break; + case USB_STATE_RUNNING: break; + case USB_STATE_ERROR: break; - }// switch( usb_task_state -} - \ No newline at end of file + } +} diff --git a/hardware/arduino/sam/system/USBHost/Usb.h b/hardware/arduino/sam/system/USBHost/Usb.h index e753962c1..adeb467c9 100644 --- a/hardware/arduino/sam/system/USBHost/Usb.h +++ b/hardware/arduino/sam/system/USBHost/Usb.h @@ -1,38 +1,36 @@ /* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ /* USB functions */ -#ifndef _usb_h_ -#define _usb_h_ +#ifndef USB_H_INCLUDED +#define USB_H_INCLUDED -#include +#include #include "ch9.h" /* Common setup data constant combinations */ -#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type -#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' -#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type +#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Get descriptor request type +#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Set request type for all but 'set feature' and 'set interface' +#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE // Get interface request type + /* HID requests */ #define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE #define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE -#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec -#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted -#define USB_RETRY_LIMIT 3 //retry limit for a transfer -#define USB_SETTLE_DELAY 200 //settle delay in milliseconds -#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code +#define USB_XFER_TIMEOUT 5000 // USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec +#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. o means NAKs are not counted +#define USB_RETRY_LIMIT 3 // Retry limit for a transfer +#define USB_SETTLE_DELAY 200 // Settle delay in milliseconds +#define USB_NAK_NOWAIT 1 // Used in Richard's PS2/Wiimote code -#define USB_NUMDEVICES 2 //number of USB devices +#define USB_NUMDEVICES 2 // Number of USB devices /* USB state machine states */ - -#define USB_STATE_MASK 0xf0 - #define USB_STATE_DETACHED 0x10 -#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 +#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 #define USB_ATTACHED_SUBSTATE_SETTLE 0x20 -#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 +#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 @@ -40,137 +38,166 @@ #define USB_STATE_CONFIGURING 0x80 #define USB_STATE_RUNNING 0x90 #define USB_STATE_ERROR 0xa0 - -// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE +#define USB_STATE_MASK 0xf0 /* USB Setup Packet Structure */ -typedef struct { - union { // offset description - byte bmRequestType; // 0 Bit-map of request type - struct { - byte recipient: 5; // Recipient of the request - byte type: 2; // Type of request - byte direction: 1; // Direction of data X-fer +typedef struct +{ + union + { // offset description + uint8_t bmRequestType; // 0 Bit-map of request type + struct + { + uint8_t recipient: 5; // Recipient of the request + uint8_t type: 2; // Type of request + uint8_t direction: 1; // Direction of data X-fer }; - }ReqType_u; - byte bRequest; // 1 Request - union { - unsigned int wValue; // 2 Depends on bRequest - struct { - byte wValueLo; - byte wValueHi; + } ReqType_u; + uint8_t bRequest; // 1 Request + union + { + uint16_t wValue; // 2 Depends on bRequest + struct + { + uint8_t wValueLo; + uint8_t wValueHi; }; - }wVal_u; - unsigned int wIndex; // 4 Depends on bRequest - unsigned int wLength; // 6 Depends on bRequest + } wVal_u; + uint16_t wIndex; // 4 Depends on bRequest + uint16_t wLength; // 6 Depends on bRequest } SETUP_PKT, *PSETUP_PKT; /* Endpoint information structure */ /* bToggle of endpoint 0 initialized to 0xff */ /* during enumeration bToggle is set to 00 */ -typedef struct { - byte epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints ) - byte Attr; // Endpoint transfer type. - unsigned int MaxPktSize; // Maximum packet size. - byte Interval; // Polling interval in frames. - byte sndToggle; //last toggle value, bitmask for HCTL toggle bits - byte rcvToggle; //last toggle value, bitmask for HCTL toggle bits +typedef struct +{ + uint32_t epAddr; // Copy from endpoint descriptor. Bit 7 indicates direction (ignored for control endpoints) + uint8_t Attr; // Endpoint transfer type. + uint16_t MaxPktSize; // Maximum packet size. + uint8_t Interval; // Polling interval in frames. + uint8_t sndToggle; // Last toggle value, bitmask for HCTL toggle bits + uint8_t rcvToggle; // Last toggle value, bitmask for HCTL toggle bits /* not sure if both are necessary */ } EP_RECORD; -/* device record structure */ -typedef struct { - EP_RECORD* epinfo; //device endpoint information - byte devclass; //device class + +/* Device record structure */ +typedef struct +{ + EP_RECORD* epinfo; // Device endpoint information + uint8_t devclass; // Device class } DEV_RECORD; - - -class USB : public MAX3421E { -//data structures -/* device table. Filled during enumeration */ -/* index corresponds to device address */ -/* each entry contains pointer to endpoint structure */ -/* and device class to use in various places */ -//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ]; -//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device - -//byte usb_task_state; - +/** + * USBHost Class + * The device table is filled during enumeration. + * Index corresponds to device address and each entry contains pointer to endpoint structure and device class to use. + */ +class USBHost +{ public: - USB( void ); - byte getUsbTaskState( void ); - void setUsbTaskState( byte state ); - EP_RECORD* getDevTableEntry( byte addr, byte ep ); - void setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr ); - byte ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - /* Control requests */ - byte getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit = USB_NAK_LIMIT ); - /**/ - byte setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); - byte setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit = USB_NAK_LIMIT ); - /**/ - byte ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); - byte ctrlStatus( byte ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); - byte inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT ); - int newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT); - byte outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT ); - byte dispatchPkt( byte token, byte ep, unsigned int nak_limit = USB_NAK_LIMIT ); - void Task( void ); + USBHost(void); + uint32_t getUsbTaskState(void); + void setUsbTaskState(uint32_t state); + EP_RECORD* getDevTableEntry(uint32_t addr, uint32_t ep); + void setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr); + uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + + /* Control requests */ + uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit = USB_NAK_LIMIT); + + /* Status requests */ + uint32_t setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit = USB_NAK_LIMIT); + + /* Transfer requests */ + uint32_t ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); + int32_t newInTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit = USB_NAK_LIMIT); + void Task(void); + private: void init(); }; -//get device descriptor -inline byte USB::getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit )); +// Get device descriptor +inline uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit)); } -//get configuration descriptor -inline byte USB::getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit )); + +// Get configuration descriptor +inline uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit)); } -//get string descriptor -inline byte USB::getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit )); + +// Get string descriptor +inline uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit)); } -//set address -inline byte USB::setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit ) { - return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit )); + +// Set address +inline uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit) +{ + return (ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0, nak_limit)); } -//set configuration -inline byte USB::setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit )); + +// Set configuration +inline uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0, nak_limit)); } -//class requests -inline byte USB::setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit )); + +// Class requests +inline uint32_t USBHost::setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, 0, nak_limit)); } -inline byte USB::getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit )); + +inline uint32_t USBHost::getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit)); } -//get HID report descriptor -inline byte USB::getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit )); + +// Get HID report descriptor +inline uint32_t USBHost::getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit)); } -inline byte USB::setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); + +inline uint32_t USBHost::setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit)); } -inline byte USB::getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) { // ** RI 04/11/09 - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); + +inline uint32_t USBHost::getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit)); } -/* returns one byte of data in dataptr */ -inline byte USB::getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit )); + +/* returns one uint8_t of data in dataptr */ +inline uint32_t USBHost::getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit)); } -inline byte USB::setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit )); - } -#endif //_usb_h_ + +inline uint32_t USBHost::setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit) +{ + return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, 0, nak_limit)); +} + +#endif /* USB_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/ch9.h b/hardware/arduino/sam/system/USBHost/ch9.h index 476634686..d2bcdd734 100644 --- a/hardware/arduino/sam/system/USBHost/ch9.h +++ b/hardware/arduino/sam/system/USBHost/ch9.h @@ -3,6 +3,8 @@ #ifndef _ch9_h_ #define _ch9_h_ +#include + /* Misc.USB constants */ #define DEV_DESCR_LEN 18 //device descriptor length #define CONF_DESCR_LEN 9 //configuration descriptor length @@ -96,73 +98,77 @@ #define HID_PROTOCOL_MOUSE 0x02 +_Pragma("pack(1)") + /* descriptor data structures */ /* Device descriptor structure */ typedef struct { - byte bLength; // Length of this descriptor. - byte bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - unsigned int bcdUSB; // USB Spec Release Number (BCD). - byte bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - byte bDeviceSubClass; // Subclass code (assigned by the USB-IF). - byte bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - byte bMaxPacketSize0; // Maximum packet size for endpoint 0. - unsigned int idVendor; // Vendor ID (assigned by the USB-IF). - unsigned int idProduct; // Product ID (assigned by the manufacturer). - unsigned int bcdDevice; // Device release number (BCD). - byte iManufacturer; // Index of String Descriptor describing the manufacturer. - byte iProduct; // Index of String Descriptor describing the product. - byte iSerialNumber; // Index of String Descriptor with the device's serial number. - byte bNumConfigurations; // Number of possible configurations. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. } USB_DEVICE_DESCRIPTOR; /* Configuration descriptor structure */ typedef struct { - byte bLength; // Length of this descriptor. - byte bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - unsigned int wTotalLength; // Total length of all descriptors for this configuration. - byte bNumInterfaces; // Number of interfaces in this configuration. - byte bConfigurationValue; // Value of this configuration (1 based). - byte iConfiguration; // Index of String Descriptor describing the configuration. - byte bmAttributes; // Configuration characteristics. - byte bMaxPower; // Maximum power consumed by this configuration. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. } USB_CONFIGURATION_DESCRIPTOR; /* Interface descriptor structure */ typedef struct { - byte bLength; // Length of this descriptor. - byte bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). - byte bInterfaceNumber; // Number of this interface (0 based). - byte bAlternateSetting; // Value of this alternate interface setting. - byte bNumEndpoints; // Number of endpoints in this interface. - byte bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - byte bInterfaceSubClass; // Subclass code (assigned by the USB-IF). - byte bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - byte iInterface; // Index of String Descriptor describing the interface. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t iInterface; // Index of String Descriptor describing the interface. } USB_INTERFACE_DESCRIPTOR; /* Endpoint descriptor structure */ typedef struct { - byte bLength; // Length of this descriptor. - byte bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). - byte bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). - byte bmAttributes; // Endpoint transfer type. - unsigned int wMaxPacketSize; // Maximum packet size. - byte bInterval; // Polling interval in frames. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. } USB_ENDPOINT_DESCRIPTOR; /* HID descriptor */ typedef struct { - byte bLength; - byte bDescriptorType; - unsigned int bcdHID; - byte bCountryCode; - byte bNumDescriptors; - byte bDescrType; - unsigned int wDescriptorLength; + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescrType; + uint16_t wDescriptorLength; } USB_HID_DESCRIPTOR; +_Pragma("pack()") + #endif // _ch9_h_ diff --git a/hardware/arduino/sam/system/libsam/chip.h b/hardware/arduino/sam/system/libsam/chip.h index fa0f9eb40..31f76f10b 100644 --- a/hardware/arduino/sam/system/libsam/chip.h +++ b/hardware/arduino/sam/system/libsam/chip.h @@ -56,9 +56,11 @@ #include "include/timetick.h" #include "include/USB_device.h" +#include "include/USB_host.h" #if SAM3XA_SERIES -#include "include/uotghs.h" +#include "include/uotghs_device.h" +#include "include/uotghs_host.h" #endif /* SAM3XA_SERIES */ #endif /* _LIB_SAM_ */ diff --git a/hardware/arduino/sam/system/libsam/include/USB_device.h b/hardware/arduino/sam/system/libsam/include/USB_device.h index 816b8bf17..6b6700831 100644 --- a/hardware/arduino/sam/system/libsam/include/USB_device.h +++ b/hardware/arduino/sam/system/libsam/include/USB_device.h @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _USB_DRIVER_ -#define _USB_DRIVER_ +#ifndef USB_DEVICE_H_INCLUDED +#define USB_DEVICE_H_INCLUDED #include @@ -403,4 +403,4 @@ typedef uint32_t iram_size_t; //! @} -#endif /* _USB_DRIVER_*/ +#endif /* USB_DEVICE_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/USB_host.h b/hardware/arduino/sam/system/libsam/include/USB_host.h new file mode 100644 index 000000000..4262f7aa6 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/USB_host.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2011 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef USB_HOST_H_INCLUDED +#define USB_HOST_H_INCLUDED + +#include + +#define tokSETUP UOTGHS_HSTPIPCFG_PTOKEN_SETUP +#define tokIN UOTGHS_HSTPIPCFG_PTOKEN_IN +#define tokOUT UOTGHS_HSTPIPCFG_PTOKEN_OUT +#define tokINHS UOTGHS_HSTPIPCFG_PTOKEN_IN +#define tokOUTHS UOTGHS_HSTPIPCFG_PTOKEN_OUT + +//! \brief Device speed +/*typedef enum { + UHD_SPEED_LOW = 0, + UHD_SPEED_FULL = 1, + UHD_SPEED_HIGH = 2, +} uhd_speed_t;*/ + +//! States of USBB interface +typedef enum { + UHD_STATE_NO_VBUS = 0, + UHD_STATE_DISCONNECTED = 1, + UHD_STATE_CONNECTED = 2, + UHD_STATE_ERROR = 3, +} uhd_vbus_state_t; + +//extern uhd_speed_t uhd_get_speed(void); + + +extern void UHD_SetStack(void (*pf_isr)(void)); +extern void UHD_Init(void); +extern void UHD_BusReset(void); +extern uhd_vbus_state_t UHD_GetVBUSState(void); +extern uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size); +extern void UHD_EP_Free(uint32_t add, uint32_t endp); +extern uint32_t UHD_EP_Read(uint32_t ul_ep, uint32_t ul_size, uint8_t* data); +extern void UHD_EP_Write(uint32_t ul_ep, uint32_t ul_size, uint8_t* data); +extern void UHD_EP_Send(uint32_t ul_ep, uint32_t ul_token_type); +extern uint32_t UHD_EP_Is_Transfer_Complete(uint32_t ul_ep, uint32_t ul_token_type); + +#endif /* USB_HOST_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/uotghs.h b/hardware/arduino/sam/system/libsam/include/uotghs_device.h similarity index 99% rename from hardware/arduino/sam/system/libsam/include/uotghs.h rename to hardware/arduino/sam/system/libsam/include/uotghs_device.h index 21b584977..13a113ae2 100644 --- a/hardware/arduino/sam/system/libsam/include/uotghs.h +++ b/hardware/arduino/sam/system/libsam/include/uotghs_device.h @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef UOTGHS_H_INCLUDED -#define UOTGHS_H_INCLUDED +#ifndef UOTGHS_DEVICE_H_INCLUDED +#define UOTGHS_DEVICE_H_INCLUDED #define MAX_ENDPOINTS 10 @@ -737,4 +737,4 @@ //! @} -#endif /* UOTGHS_H_INCLUDED */ +#endif /* UOTGHS_DEVICE_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/uotghs_host.h b/hardware/arduino/sam/system/libsam/include/uotghs_host.h new file mode 100644 index 000000000..d634f124f --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/uotghs_host.h @@ -0,0 +1,378 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef UOTGHS_HOST_H_INCLUDED +#define UOTGHS_HOST_H_INCLUDED + +//! \ingroup usb_host_group +//! \defgroup uhd_group USB Host Driver (UHD) +//! UOTGHS low-level driver for USB host mode +//! +//! @{ + +//! @name UOTGHS Host IP properties +//! +//! @{ +//! Get maximal number of endpoints +#define uhd_get_pipe_max_nbr() (9) +#define UOTGHS_EPT_NUM (uhd_get_pipe_max_nbr()+1) +//! @} + +//! @name Host Vbus line control +//! +//! VBOF is an optional output pin which allows to enable or disable +//! the external VBus generator. +//! +//! @{ +//! Enables hardware control of USB_VBOF output pin when a Vbus error occur +#define uhd_enable_vbus_error_hw_control() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC)) +//! Disables hardware control of USB_VBOF output pin when a Vbus error occur +#define uhd_disable_vbus_error_hw_control() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC)) + +//! Pin and function for USB_VBOF according to configuration from USB_VBOF +#define USB_VBOF_PIN USB_VBOF_GPIO +#define USB_VBOF_FUNCTION USB_VBOF_FLAGS +//! Output USB_VBOF onto its pin +#define uhd_output_vbof_pin() do {\ + pio_configure_pin(USB_VBOF_PIN, USB_VBOF_FUNCTION); \ +} while (0) + +//! Set USB_VBOF output pin polarity +#define uhd_set_vbof_active_high() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO)) +#define uhd_set_vbof_active_low() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO)) +//! Requests VBus activation +#define uhd_enable_vbus() (Set_bits(UOTGHS->UOTGHS_SFR, UOTGHS_SR_VBUSRQ)) +//! Requests VBus deactivation +#define uhd_disable_vbus() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SR_VBUSRQ)) +//! Tests if VBus activation has been requested +#define Is_uhd_vbus_enabled() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSRQ)) +//! @} + +//! @name Host Vbus line monitoring +//! +//! The VBus level is always checked by USBC hardware. +//! +//! @{ +#define uhd_enable_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE)) +#define uhd_disable_vbus_error_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE)) +#define Is_uhd_vbus_error_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE)) +#define uhd_ack_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SCR_VBERRIC)) +#define Is_uhd_vbus_error_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBERRI)) +//! @} + +#define uhd_ack_errors_interrupt() (UOTGHS->UOTGHS_SCR = (UOTGHS_SCR_VBERRIC|UOTGHS_SCR_BCERRIC|UOTGHS_SCR_HNPERRIC|UOTGHS_SCR_STOIC)) +#define Is_uhd_errors_interrupt() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE|UOTGHS_CTRL_BCERRE|UOTGHS_CTRL_HNPERRE|UOTGHS_CTRL_STOE)) +#define uhd_enable_suspend_error_interrupt() +#define uhd_enable_hnp_error_interrupt() +#define uhd_enable_bconn_error_interrupt() + +//! @name USB device connection/disconnection monitoring +//! @{ +#define uhd_enable_connection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DCONNIES) +#define uhd_disable_connection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DCONNIEC) +#define Is_uhd_connection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DCONNIE)) +#define uhd_ack_connection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC) +#define Is_uhd_connection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DCONNI)) + +#define uhd_enable_disconnection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DDISCIES) +#define uhd_disable_disconnection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DDISCIEC) +#define Is_uhd_disconnection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DDISCIE)) +#define uhd_ack_disconnection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DDISCIC) +#define Is_uhd_disconnection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DDISCI)) +//! @} + +//! @name USB device speed control +//! @{ +#define uhd_get_speed_mode() (Rd_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_SPEED_Msk)) +#define Is_uhd_low_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_LOW_SPEED) +#define Is_uhd_full_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_FULL_SPEED) +#define Is_uhd_high_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_HIGH_SPEED) +//! Enable high speed mode +# define uhd_enable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_HIGH_SPEED)) +//! Disable high speed mode +# define uhd_disable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_FORCED_FS)) +//! @} + +//! @name Bus events control +//! These macros manage the bus events: reset, SOF, resume, wakeup. +//! @{ + +//! Initiates a reset event +//! @{ +#define uhd_start_reset() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET)) +#define Is_uhd_starting_reset() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET)) +#define uhd_stop_reset() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET)) + +#define uhd_enable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSTIES) +#define uhd_disable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSTIEC) +#define Is_uhd_reset_sent_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSTIE)) +#define uhd_ack_reset_sent() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSTIC) +#define Is_uhd_reset_sent() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSTI)) +//! @} + +//! Initiates a SOF events +//! @{ +#define uhd_enable_sof() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE)) +#define uhd_disable_sof() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE)) +#define Is_uhd_sof_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE)) +#define uhd_get_sof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_FNUM_Msk)>>UOTGHS_HSTFNUM_FNUM_Pos) +#define uhd_get_microsof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_MFNUM_Msk)>>UOTGHS_HSTFNUM_MFNUM_Pos) +#define uhd_get_frame_position() (Rd_bits(UOTGHS->UOTGHS_HSTFNUM, UOTGHS_HSTFNUM_FLENHIGH_Msk)) +#define uhd_enable_sof_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HSOFIES) +#define uhd_disable_sof_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HSOFIEC) +#define Is_uhd_sof_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HSOFIE)) +#define uhd_ack_sof() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HSOFIC) +#define Is_uhd_sof() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HSOFI)) +//! @} + +//! Initiates a resume event +//! It is called downstream resume event. +//! @{ +#define uhd_send_resume() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME)) +#define Is_uhd_sending_resume() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME)) + +#define uhd_enable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSMEDIES) +#define uhd_disable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSMEDIEC) +#define Is_uhd_downstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSMEDIE)) +#define uhd_ack_downstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSMEDIC) +#define Is_uhd_downstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSMEDI)) +//! @} + +//! Detection of a wake-up event +//! A wake-up event is received when the host controller is in the suspend mode: +//! - and an upstream resume from the peripheral is detected. +//! - and a peripheral disconnection is detected. +//! @{ +#define uhd_enable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HWUPIES) +#define uhd_disable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC) +#define Is_uhd_wakeup_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HWUPIE)) +#define uhd_ack_wakeup() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HWUPIC) +#define Is_uhd_wakeup() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HWUPI)) + +#define uhd_enable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RXRSMIES) +#define uhd_disable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RXRSMIEC) +#define Is_uhd_upstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RXRSMIE)) +#define uhd_ack_upstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RXRSMIC) +#define Is_uhd_upstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RXRSMI)) +//! @} +//! @} + + +//! @name Pipes management +//! @{ + +//! USB address of pipes +//! @{ +#define uhd_configure_address(p, addr) \ + (Wr_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \ + UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3), addr)) +#define uhd_get_configured_address(p) \ + (Rd_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \ + UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3))) +//! @} + +//! Pipe enable +//! Enable, disable, reset, freeze +//! @{ +#define uhd_enable_pipe(p) \ + (Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))) +#define uhd_disable_pipe(p) \ + (Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))) +#define Is_uhd_pipe_enabled(p) \ + (Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))) +#define uhd_reset_pipe(p) \ + (Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))); \ + (Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))) +#define Is_uhd_resetting_pipe(p) \ + (Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))) +#define uhd_freeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PFREEZES) +#define uhd_unfreeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PFREEZEC) +#define Is_uhd_pipe_frozen(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PFREEZE)) +#define uhd_reset_data_toggle(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RSTDTS) +#define Is_uhd_data_toggle_reset(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RSTDT)) +//! @} + +//! Pipe configuration +//! @{ +#define uhd_configure_pipe_int_req_freq(p,freq) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk, (freq))) +#define uhd_get_pipe_int_req_freq(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk)) +#define uhd_configure_pipe_endpoint_number(p,ep) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PEPNUM_Msk, (ep))) +#define uhd_get_pipe_endpoint_address(p) \ + (uhd_is_pipe_in(p) ?\ + (uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_IN) :\ + (uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_OUT)) +#define uhd_get_pipe_endpoint_number(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PEPNUM_Msk))) +#define uhd_configure_pipe_type(p, type) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk, type)) +#define uhd_get_pipe_type(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk)) +#define uhd_enable_pipe_bank_autoswitch(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW)) +#define uhd_disable_pipe_bank_autoswitch(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW)) +#define Is_uhd_pipe_bank_autoswitch_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW)) +#define uhd_configure_pipe_token(p, token) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk, token)) +#define uhd_get_pipe_token(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk)) +#define uhd_is_pipe_in(p) (UOTGHS_HSTPIPCFG_PTOKEN_IN==uhd_get_pipe_token(p)) +#define uhd_is_pipe_out(p) (UOTGHS_HSTPIPCFG_PTOKEN_OUT==uhd_get_pipe_token(p)) +//! Bounds given integer size to allowed range and rounds it up to the nearest +//! available greater size, then applies register format of UOTGHS controller +//! for pipe size bit-field. +#define uhd_format_pipe_size(size) \ + (32 - clz(((uint32_t)min(max(size, 8), 1024) << 1) - 1) - 1 - 3) +#define uhd_configure_pipe_size(p,size) \ + (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PSIZE_Msk, uhd_format_pipe_size(size))) +#define uhd_get_pipe_size(p) (8<<((Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PSIZE_Msk)))>> UOTGHS_HSTPIPCFG_PSIZE_Pos)) +#define uhd_configure_pipe_bank(p,bank) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk, (bank))) +#define uhd_get_pipe_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk)) +#define uhd_allocate_memory(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC)) +#define uhd_unallocate_memory(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC)) +#define Is_uhd_memory_allocated(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC)) + +//! Enable PING management only available in HS mode +# define uhd_enable_ping(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PINGEN)) +//#endif +#define uhd_configure_pipe(p, freq, ep_num, type, token, size, bank, bank_switch) \ + (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p],\ + (bank)|\ + ((uhd_format_pipe_size(size)<UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK)) +//! @} + +//! Pipe main interrupts management +//! @{ +#define uhd_enable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIER = (UOTGHS_HSTIER_PEP_0 << (p))) +#define uhd_disable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIDR = (UOTGHS_HSTIDR_PEP_0 << (p))) +#define Is_uhd_pipe_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_PEP_0 << (p))) +#define Is_uhd_pipe_interrupt(p) (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_PEP_0 << (p))) +//! returns the lowest pipe number generating a pipe interrupt or UOTGHS_EPT_NUM if none +#define uhd_get_interrupt_pipe_number() \ + (ctz(((UOTGHS->UOTGHS_HSTISR >> 8) & (UOTGHS->UOTGHS_HSTIMR >> 8)) | (1 << UOTGHS_EPT_NUM))) +//! @} + +//! Pipe overflow and underflow for isochronous and interrupt endpoints +//! @{ +#define uhd_enable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_OVERFIES) +#define uhd_disable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_OVERFIEC) +#define Is_uhd_overflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_OVERFIE)) +#define uhd_ack_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_OVERFIC) +#define Is_uhd_overflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_OVERFI)) + +#define uhd_enable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_UNDERFIES) +#define uhd_disable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_UNDERFIEC) +#define Is_uhd_underflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_UNDERFIE)) +#define uhd_ack_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_UNDERFIC) +#define Is_uhd_underflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_UNDERFI)) +//! @} + +//! USB packet errors management +//! @{ +#define uhd_enable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXSTALLDES) +#define uhd_disable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXSTALLDEC) +#define Is_uhd_stall_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXSTALLDE)) +#define uhd_ack_stall(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXSTALLDIC) +#define Is_uhd_stall(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXSTALLDI)) + +#define uhd_enable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PERRES) +#define uhd_disable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PERREC) +#define Is_uhd_pipe_error_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PERRE)) +#define uhd_ack_all_errors(p) (UOTGHS->UOTGHS_HSTPIPERR[p] = 0UL) +#define Is_uhd_pipe_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PERRI)) +#define uhd_error_status(p) (UOTGHS->UOTGHS_HSTPIPERR[p]) +#define Is_uhd_bad_data_toggle(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATATGL)) +#define Is_uhd_data_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATAPID)) +#define Is_uhd_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_PID)) +#define Is_uhd_timeout_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_TIMEOUT)) +#define Is_uhd_crc16_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_CRC16)) +#define uhd_get_error_counter(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_COUNTER)) +//! @} + +//! Pipe data management +//! @{ +#define uhd_data_toggle(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_DTSEQ)) + +#define uhd_enable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NBUSYBKES) +#define uhd_disable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NBUSYBKEC) +#define Is_uhd_bank_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NBUSYBKE)) +#define uhd_nb_busy_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NBUSYBK_Msk)) +#define uhd_current_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CURRBK_Msk )) + +#define uhd_enable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_SHORTPACKETES) +#define uhd_disable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_SHORTPACKETIEC) +#define Is_uhd_short_packet_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_SHORTPACKETIE)) ) +#define uhd_ack_short_packet(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_SHORTPACKETIC) +#define Is_uhd_short_packet(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_SHORTPACKETI)) +#define uhd_byte_count(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PBYCT_Msk)) + +#define Is_uhd_fifocon(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_FIFOCON)) +#define uhd_ack_fifocon(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_FIFOCONC) + +#define uhd_enable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXSTPES) +#define uhd_disable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXSTPEC) +#define Is_uhd_setup_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXSTPE)) +#define uhd_ack_setup_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXSTPIC) +#define Is_uhd_setup_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXSTPI)) + +#define uhd_enable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXINES) +#define uhd_disable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXINEC) +#define Is_uhd_in_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXINE)) +#define uhd_ack_in_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXINIC) +#define Is_uhd_in_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXINI)) + +#define uhd_enable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXOUTES) +#define uhd_disable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXOUTEC) +#define Is_uhd_out_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXOUTE)) +#define uhd_ack_out_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXOUTIC) +#define Is_uhd_out_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXOUTI)) +#define uhd_raise_out_ready(p) (UOTGHS->UOTGHS_HSTPIPIFR[p] = UOTGHS_HSTPIPIFR_TXOUTIS) + +#define uhd_enable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NAKEDES) +#define uhd_disable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NAKEDEC) +#define Is_uhd_nak_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NAKEDE)) +#define uhd_ack_nak_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_NAKEDIC) +#define Is_uhd_nak_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NAKEDI)) + +#define Is_uhd_read_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL)) +#define Is_uhd_write_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL )) + +#define uhd_enable_continuous_in_mode(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE)) +#define uhd_disable_continuous_in_mode(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE)) +#define Is_uhd_continuous_in_mode_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE)) + +#define uhd_in_request_number(p, in_num) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], (in_num)-1)) +#define uhd_get_in_request_number(p) (((Rd_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INRQ_Msk))>>UOTGHS_HSTPIPINRQ_INRQ_Pos)+1) +//! @} + +//! Maximum transfer size on USB DMA +#define UHD_PIPE_MAX_TRANS 0x8000 + +//! Get 64-, 32-, 16- or 8-bit access to FIFO data register of selected pipe. +//! @param p Target Pipe number +//! @param scale Data scale in bits: 64, 32, 16 or 8 +//! @return Volatile 64-, 32-, 16- or 8-bit data pointer to FIFO data register +//! @warning It is up to the user of this macro to make sure that all accesses +//! are aligned with their natural boundaries except 64-bit accesses which +//! require only 32-bit alignment. +//! @warning It is up to the user of this macro to make sure that used HSB +//! addresses are identical to the DPRAM internal pointer modulo 32 bits. +#define uhd_get_pipe_fifo_access(p, scale) \ + (((volatile TPASTE2(U, scale) (*)[UHD_PIPE_MAX_TRANS / ((scale) / 8)])UOTGHS_RAM_ADDR)[(p)]) + +#endif /* UOTGHS_HOST_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/source/uotghs.c b/hardware/arduino/sam/system/libsam/source/uotghs.c index 10d1c9505..061746571 100644 --- a/hardware/arduino/sam/system/libsam/source/uotghs.c +++ b/hardware/arduino/sam/system/libsam/source/uotghs.c @@ -17,22 +17,10 @@ */ #include "chip.h" -#include #if SAM3XA_SERIES -//#define TRACE_UOTGHS(x) x -#define TRACE_UOTGHS(x) - -static void (*gpf_isr)(void) = (0UL); - -static volatile uint32_t ul_send_fifo_ptr[MAX_ENDPOINTS]; -static volatile uint32_t ul_recv_fifo_ptr[MAX_ENDPOINTS]; - -void UDD_SetStack(void (*pf_isr)(void)) -{ - gpf_isr = pf_isr; -} +void (*gpf_isr)(void) = (0UL); void UOTGHS_Handler( void ) { @@ -40,291 +28,4 @@ void UOTGHS_Handler( void ) gpf_isr(); } -uint32_t UDD_Init(void) -{ - uint32_t i; - - for (i = 0; i < MAX_ENDPOINTS; ++i) - { - ul_send_fifo_ptr[i] = 0; - ul_recv_fifo_ptr[i] = 0; - } - - // Enables the USB Clock - pmc_enable_periph_clk(ID_UOTGHS); - pmc_enable_upll_clock(); - pmc_switch_udpck_to_upllck(0); // div=0+1 - pmc_enable_udpck(); - - // Configure interrupts - NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL); - NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); - - // Always authorize asynchrone USB interrupts to exit from sleep mode - // for SAM3 USB wake up device except BACKUP mode - //pmc_set_fast_startup_input(PMC_FSMR_USBAL); - - // ID pin not used then force device mode - otg_disable_id_pin(); - otg_force_device_mode(); - - // Enable USB hardware - otg_disable_pad(); - otg_enable_pad(); - otg_enable(); - otg_unfreeze_clock(); - - // Check USB clock - //while (!Is_otg_clock_usable()) - // ; - - udd_low_speed_disable(); - udd_high_speed_disable(); - - //otg_ack_vbus_transition(); - // Force Vbus interrupt in case of Vbus always with a high level - // This is possible with a short timing between a Host mode stop/start. - /*if (Is_otg_vbus_high()) { - otg_raise_vbus_transition(); - } - otg_enable_vbus_interrupt();*/ - otg_freeze_clock(); - - return 0UL ; -} - -void UDD_Attach(void) -{ - irqflags_t flags = cpu_irq_save(); - - TRACE_UOTGHS(printf("=> UDD_Attach\r\n");) - - otg_unfreeze_clock(); - - // Check USB clock because the source can be a PLL - while (!Is_otg_clock_usable()); - - // Authorize attach if Vbus is present - udd_attach_device(); - - // Enable USB line events - udd_enable_reset_interrupt(); - //udd_enable_sof_interrupt(); - - cpu_irq_restore(flags); -} - -void UDD_Detach(void) -{ - TRACE_UOTGHS(printf("=> UDD_Detach\r\n");) - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH; -} - -void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg ) -{ - ul_ep_nb = ul_ep_nb & 0xF; // EP range is 0..9, hence mask is 0xF. - - TRACE_UOTGHS(printf("=> UDD_InitEP : init EP %d\r\n", ul_ep_nb);) - - // Configure EP - UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = ul_ep_cfg; - // Enable EP - udd_enable_endpoint(ul_ep_nb); - - if (!Is_udd_endpoint_configured(ul_ep_nb)) { - TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);) - } -} - - -void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size) -{ - uint32_t ul_ep_nb ; - - for (ul_ep_nb = 1; ul_ep_nb < ul_eps_table_size; ul_ep_nb++) - { - // Configure EP - UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = eps_table[ul_ep_nb]; - // Enable EP - udd_enable_endpoint(ul_ep_nb); - - if (!Is_udd_endpoint_configured(ul_ep_nb)) { - TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);) - } - } -} - -// Wait until ready to accept IN packet. -void UDD_WaitIN(void) -{ - while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_TXINI)) - ; -} - -void UDD_WaitOUT(void) -{ - while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI)) - ; -} - -// Send packet. -void UDD_ClearIN(void) -{ - TRACE_UOTGHS(printf("=> UDD_ClearIN: sent %d bytes\r\n", ul_send_fifo_ptr[EP0]);) - - UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC; - ul_send_fifo_ptr[EP0] = 0; -} - -void UDD_ClearOUT(void) -{ - UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_RXOUTIC; - ul_recv_fifo_ptr[EP0] = 0; -} - -// Wait for IN FIFO to be ready to accept data or OUT FIFO to receive data. -// Return true if new IN FIFO buffer available. -uint32_t UDD_WaitForINOrOUT(void) -{ - while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & (UOTGHS_DEVEPTISR_TXINI | UOTGHS_DEVEPTISR_RXOUTI))) - ; - return ((UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI) == 0); -} - -uint32_t UDD_ReceivedSetupInt(void) -{ - return UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXSTPI; -} - -void UDD_ClearSetupInt(void) -{ - UOTGHS->UOTGHS_DEVEPTICR[EP0] = (UOTGHS_DEVEPTICR_RXSTPIC); -} - -uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len) -{ - const uint8_t *ptr_src = data; - uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); - uint32_t i; - - TRACE_UOTGHS(printf("=> UDD_Send (1): ep=%d ul_send_fifo_ptr=%d len=%d\r\n", ep, ul_send_fifo_ptr[ep], len);) - - if (ep == EP0) - { - if (ul_send_fifo_ptr[ep] + len > EP0_SIZE) - len = EP0_SIZE - ul_send_fifo_ptr[ep]; - } - else - { - if (ul_send_fifo_ptr[ep] + len > EPX_SIZE) - len = EPX_SIZE - ul_send_fifo_ptr[ep]; - } - - for (i = 0, ptr_dest += ul_send_fifo_ptr[ep]; i < len; ++i) - *ptr_dest++ = *ptr_src++; - - ul_send_fifo_ptr[ep] += i; - - - if (ep == EP0) - { - TRACE_UOTGHS(printf("=> UDD_Send (2): ep=%d ptr_dest=%d maxlen=%d\r\n", ep, ul_send_fifo_ptr[ep], EP0_SIZE);) - if (ul_send_fifo_ptr[ep] == EP0_SIZE) - { - UDD_ClearIN(); // Fifo is full, release this packet - UDD_WaitIN(); // Wait for new FIFO buffer to be ready - } - } - else - { - if (ul_send_fifo_ptr[ep] == EPX_SIZE) - { - UDD_ClearIN(); // Fifo is full, release this packet - UDD_WaitIN(); // Wait for new FIFO buffer to be ready - } - } - - return len; -} - -void UDD_Send8(uint32_t ep, uint8_t data ) -{ - uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); - - TRACE_UOTGHS(printf("=> UDD_Send8 : ul_send_fifo_ptr=%d data=0x%x\r\n", ul_send_fifo_ptr[ep], data);) - - ptr_dest[ul_send_fifo_ptr[ep]] = data; - ul_send_fifo_ptr[ep] += 1; -} - -uint8_t UDD_Recv8(uint32_t ep) -{ - uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); - uint8_t data = ptr_dest[ul_recv_fifo_ptr[ep]]; - - TRACE_UOTGHS(printf("=> UDD_Recv8 : ul_recv_fifo_ptr=%d\r\n", ul_recv_fifo_ptr[ep]);) - - ul_recv_fifo_ptr[ep] += 1; - return data; -} - -void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len) -{ - uint8_t *ptr_src = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); - uint8_t *ptr_dest = data; - uint32_t i; - - for (i = 0, ptr_src += ul_recv_fifo_ptr[ep]; i < len; ++i) - *ptr_dest++ = *ptr_src++; - - ul_recv_fifo_ptr[ep] += i; -} - -void UDD_Stall(void) -{ - UOTGHS->UOTGHS_DEVEPT = (UOTGHS_DEVEPT_EPEN0 << EP0); - UOTGHS->UOTGHS_DEVEPTIER[EP0] = UOTGHS_DEVEPTIER_STALLRQS; -} - - -uint32_t UDD_FifoByteCount(uint32_t ep) -{ - return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos); -} - -void UDD_ReleaseRX(uint32_t ep) -{ - TRACE_UOTGHS(puts("=> UDD_ReleaseRX\r\n");) - UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKOUTIC | UOTGHS_DEVEPTICR_RXOUTIC); - UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC; - ul_recv_fifo_ptr[ep] = 0; -} - -void UDD_ReleaseTX(uint32_t ep) -{ - TRACE_UOTGHS(printf("=> UDD_ReleaseTX ep=%d\r\n", ep);) - UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKINIC | UOTGHS_DEVEPTICR_RXOUTIC | UOTGHS_DEVEPTICR_TXINIC); - UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC; - ul_send_fifo_ptr[ep] = 0; -} - -// Return true if the current bank is not full. -uint32_t UDD_ReadWriteAllowed(uint32_t ep) -{ - return (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_RWALL); -} - -void UDD_SetAddress(uint32_t addr) -{ - TRACE_UOTGHS(printf("=> UDD_SetAddress : setting address to %d\r\n", addr);) - - udd_configure_address(addr); - udd_enable_address(); -} - -uint32_t UDD_GetFrameNumber(void) -{ - return udd_frame_number(); -} - #endif /* SAM3XA_SERIES */ diff --git a/hardware/arduino/sam/system/libsam/source/uotghs_device.c b/hardware/arduino/sam/system/libsam/source/uotghs_device.c new file mode 100644 index 000000000..a589767f2 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/uotghs_device.c @@ -0,0 +1,324 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "chip.h" +#include + +#if SAM3XA_SERIES + +//#define TRACE_UOTGHS(x) x +#define TRACE_UOTGHS(x) + +extern void (*gpf_isr)(void); + +static volatile uint32_t ul_send_fifo_ptr[MAX_ENDPOINTS]; +static volatile uint32_t ul_recv_fifo_ptr[MAX_ENDPOINTS]; + +void UDD_SetStack(void (*pf_isr)(void)) +{ + gpf_isr = pf_isr; +} + +uint32_t UDD_Init(void) +{ + uint32_t i; + + for (i = 0; i < MAX_ENDPOINTS; ++i) + { + ul_send_fifo_ptr[i] = 0; + ul_recv_fifo_ptr[i] = 0; + } + + // Enables the USB Clock + pmc_enable_periph_clk(ID_UOTGHS); + pmc_enable_upll_clock(); + pmc_switch_udpck_to_upllck(0); // div=0+1 + pmc_enable_udpck(); + + // Configure interrupts + NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL); + NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); + + // Always authorize asynchrone USB interrupts to exit from sleep mode + // for SAM3 USB wake up device except BACKUP mode + //pmc_set_fast_startup_input(PMC_FSMR_USBAL); + + // ID pin not used then force device mode + otg_disable_id_pin(); + otg_force_device_mode(); + + // Enable USB hardware + otg_disable_pad(); + otg_enable_pad(); + otg_enable(); + otg_unfreeze_clock(); + + // Check USB clock + //while (!Is_otg_clock_usable()) + // ; + + udd_low_speed_disable(); + udd_high_speed_disable(); + + //otg_ack_vbus_transition(); + // Force Vbus interrupt in case of Vbus always with a high level + // This is possible with a short timing between a Host mode stop/start. + /*if (Is_otg_vbus_high()) { + otg_raise_vbus_transition(); + } + otg_enable_vbus_interrupt();*/ + otg_freeze_clock(); + + return 0UL ; +} + +void UDD_Attach(void) +{ + irqflags_t flags = cpu_irq_save(); + + TRACE_UOTGHS(printf("=> UDD_Attach\r\n");) + + otg_unfreeze_clock(); + + // Check USB clock because the source can be a PLL + while (!Is_otg_clock_usable()); + + // Authorize attach if Vbus is present + udd_attach_device(); + + // Enable USB line events + udd_enable_reset_interrupt(); + //udd_enable_sof_interrupt(); + + cpu_irq_restore(flags); +} + +void UDD_Detach(void) +{ + TRACE_UOTGHS(printf("=> UDD_Detach\r\n");) + UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH; +} + +void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg ) +{ + ul_ep_nb = ul_ep_nb & 0xF; // EP range is 0..9, hence mask is 0xF. + + TRACE_UOTGHS(printf("=> UDD_InitEP : init EP %d\r\n", ul_ep_nb);) + + // Configure EP + UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = ul_ep_cfg; + // Enable EP + udd_enable_endpoint(ul_ep_nb); + + if (!Is_udd_endpoint_configured(ul_ep_nb)) { + TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);) + } +} + + +void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size) +{ + uint32_t ul_ep_nb ; + + for (ul_ep_nb = 1; ul_ep_nb < ul_eps_table_size; ul_ep_nb++) + { + // Configure EP + UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = eps_table[ul_ep_nb]; + // Enable EP + udd_enable_endpoint(ul_ep_nb); + + if (!Is_udd_endpoint_configured(ul_ep_nb)) { + TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);) + } + } +} + +// Wait until ready to accept IN packet. +void UDD_WaitIN(void) +{ + while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_TXINI)) + ; +} + +void UDD_WaitOUT(void) +{ + while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI)) + ; +} + +// Send packet. +void UDD_ClearIN(void) +{ + TRACE_UOTGHS(printf("=> UDD_ClearIN: sent %d bytes\r\n", ul_send_fifo_ptr[EP0]);) + + UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC; + ul_send_fifo_ptr[EP0] = 0; +} + +void UDD_ClearOUT(void) +{ + UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_RXOUTIC; + ul_recv_fifo_ptr[EP0] = 0; +} + +// Wait for IN FIFO to be ready to accept data or OUT FIFO to receive data. +// Return true if new IN FIFO buffer available. +uint32_t UDD_WaitForINOrOUT(void) +{ + while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & (UOTGHS_DEVEPTISR_TXINI | UOTGHS_DEVEPTISR_RXOUTI))) + ; + return ((UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI) == 0); +} + +uint32_t UDD_ReceivedSetupInt(void) +{ + return UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXSTPI; +} + +void UDD_ClearSetupInt(void) +{ + UOTGHS->UOTGHS_DEVEPTICR[EP0] = (UOTGHS_DEVEPTICR_RXSTPIC); +} + +uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len) +{ + const uint8_t *ptr_src = data; + uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); + uint32_t i; + + TRACE_UOTGHS(printf("=> UDD_Send (1): ep=%d ul_send_fifo_ptr=%d len=%d\r\n", ep, ul_send_fifo_ptr[ep], len);) + + if (ep == EP0) + { + if (ul_send_fifo_ptr[ep] + len > EP0_SIZE) + len = EP0_SIZE - ul_send_fifo_ptr[ep]; + } + else + { + if (ul_send_fifo_ptr[ep] + len > EPX_SIZE) + len = EPX_SIZE - ul_send_fifo_ptr[ep]; + } + + for (i = 0, ptr_dest += ul_send_fifo_ptr[ep]; i < len; ++i) + *ptr_dest++ = *ptr_src++; + + ul_send_fifo_ptr[ep] += i; + + + if (ep == EP0) + { + TRACE_UOTGHS(printf("=> UDD_Send (2): ep=%d ptr_dest=%d maxlen=%d\r\n", ep, ul_send_fifo_ptr[ep], EP0_SIZE);) + if (ul_send_fifo_ptr[ep] == EP0_SIZE) + { + UDD_ClearIN(); // Fifo is full, release this packet + UDD_WaitIN(); // Wait for new FIFO buffer to be ready + } + } + else + { + if (ul_send_fifo_ptr[ep] == EPX_SIZE) + { + UDD_ClearIN(); // Fifo is full, release this packet + UDD_WaitIN(); // Wait for new FIFO buffer to be ready + } + } + + return len; +} + +void UDD_Send8(uint32_t ep, uint8_t data ) +{ + uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); + + TRACE_UOTGHS(printf("=> UDD_Send8 : ul_send_fifo_ptr=%d data=0x%x\r\n", ul_send_fifo_ptr[ep], data);) + + ptr_dest[ul_send_fifo_ptr[ep]] = data; + ul_send_fifo_ptr[ep] += 1; +} + +uint8_t UDD_Recv8(uint32_t ep) +{ + uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); + uint8_t data = ptr_dest[ul_recv_fifo_ptr[ep]]; + + TRACE_UOTGHS(printf("=> UDD_Recv8 : ul_recv_fifo_ptr=%d\r\n", ul_recv_fifo_ptr[ep]);) + + ul_recv_fifo_ptr[ep] += 1; + return data; +} + +void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len) +{ + uint8_t *ptr_src = (uint8_t *) &udd_get_endpoint_fifo_access8(ep); + uint8_t *ptr_dest = data; + uint32_t i; + + for (i = 0, ptr_src += ul_recv_fifo_ptr[ep]; i < len; ++i) + *ptr_dest++ = *ptr_src++; + + ul_recv_fifo_ptr[ep] += i; +} + +void UDD_Stall(void) +{ + UOTGHS->UOTGHS_DEVEPT = (UOTGHS_DEVEPT_EPEN0 << EP0); + UOTGHS->UOTGHS_DEVEPTIER[EP0] = UOTGHS_DEVEPTIER_STALLRQS; +} + + +uint32_t UDD_FifoByteCount(uint32_t ep) +{ + return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos); +} + +void UDD_ReleaseRX(uint32_t ep) +{ + TRACE_UOTGHS(puts("=> UDD_ReleaseRX\r\n");) + UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKOUTIC | UOTGHS_DEVEPTICR_RXOUTIC); + UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC; + ul_recv_fifo_ptr[ep] = 0; +} + +void UDD_ReleaseTX(uint32_t ep) +{ + TRACE_UOTGHS(printf("=> UDD_ReleaseTX ep=%d\r\n", ep);) + UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKINIC | UOTGHS_DEVEPTICR_RXOUTIC | UOTGHS_DEVEPTICR_TXINIC); + UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC; + ul_send_fifo_ptr[ep] = 0; +} + +// Return true if the current bank is not full. +uint32_t UDD_ReadWriteAllowed(uint32_t ep) +{ + return (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_RWALL); +} + +void UDD_SetAddress(uint32_t addr) +{ + TRACE_UOTGHS(printf("=> UDD_SetAddress : setting address to %d\r\n", addr);) + + udd_configure_address(addr); + udd_enable_address(); +} + +uint32_t UDD_GetFrameNumber(void) +{ + return udd_frame_number(); +} + +#endif /* SAM3XA_SERIES */ diff --git a/hardware/arduino/sam/system/libsam/source/uotghs_host.c b/hardware/arduino/sam/system/libsam/source/uotghs_host.c new file mode 100644 index 000000000..ae5cdf176 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/uotghs_host.c @@ -0,0 +1,404 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "chip.h" +#include + +#if SAM3XA_SERIES + +#define TRACE_UOTGHS(x) x +//#define TRACE_UOTGHS(x) + +extern void (*gpf_isr)(void); + +static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS; + +static void UHD_ISR(void) +{ + // Manage dis/connection event + if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) { + printf(">>> UHD_ISR : Disconnection INT\r\n"); + uhd_ack_disconnection(); + uhd_disable_disconnection_int(); + // Stop reset signal, in case of disconnection during reset + uhd_stop_reset(); + // Disable wakeup/resumes interrupts, + // in case of disconnection during suspend mode + //UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC + // | UOTGHS_HSTIDR_RSMEDIEC + // | UOTGHS_HSTIDR_RXRSMIEC; + uhd_ack_connection(); + uhd_enable_connection_int(); + uhd_state = UHD_STATE_DISCONNECTED; + return; + } + if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) { + printf(">>> UHD_ISR : Connection INT\r\n"); + uhd_ack_connection(); + uhd_disable_connection_int(); + uhd_ack_disconnection(); + uhd_enable_disconnection_int(); + //uhd_enable_sof(); + uhd_state = UHD_STATE_CONNECTED; + return; + } + + // Manage Vbus error + if (Is_uhd_vbus_error_interrupt()) + { + printf(">>> UHD_ISR : VBUS error INT\r\n"); + uhd_ack_vbus_error_interrupt(); + uhd_state = UHD_STATE_ERROR; + return; + } + + // Check USB clock ready after asynchronous interrupt + while (!Is_otg_clock_usable()) + ; + otg_unfreeze_clock(); + + // Manage Vbus state change + if (Is_otg_vbus_transition()) + { + otg_ack_vbus_transition(); + if (Is_otg_vbus_high()) + { + printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n"); + uhd_state = UHD_STATE_DISCONNECTED; + } + else + { + printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n"); + otg_freeze_clock(); + uhd_state = UHD_STATE_NO_VBUS; + } + printf(">>> UHD_ISR : VBUS transition INT : done.\r\n"); + return; + } + + // Other errors + if (Is_uhd_errors_interrupt()) + { + printf(">>> UHD_ISR : Other error INT\r\n"); + uhd_ack_errors_interrupt(); + return; + } +} + +void UHD_SetStack(void (*pf_isr)(void)) +{ + gpf_isr = pf_isr; +} + +void UHD_Init(void) +{ + irqflags_t flags; + + // To avoid USB interrupt before end of initialization + flags = cpu_irq_save(); + + // Setup USB Host interrupt callback + UHD_SetStack(&UHD_ISR); + + // Enables the USB Clock + pmc_enable_upll_clock(); + pmc_switch_udpck_to_upllck(0); // div=0+1 + pmc_enable_udpck(); + pmc_enable_periph_clk(ID_UOTGHS); + + // Always authorize asynchronous USB interrupts to exit of sleep mode + // For SAM3 USB wake up device except BACKUP mode + NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0); + NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); + + // ID pin not used then force host mode + otg_disable_id_pin(); + otg_force_host_mode(); + + // Signal is active low (because all SAM3X Pins are high after startup) + // Hence VBOF must be low after connection request to power up the remote device + uhd_set_vbof_active_low(); + + otg_enable_pad(); + otg_enable(); + + otg_unfreeze_clock(); + + // Check USB clock + while (!Is_otg_clock_usable()) + ; + + // Clear all interrupts that may have been set by a previous host mode + UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC + | UOTGHS_HSTICR_HSOFIC | UOTGHS_HSTICR_HWUPIC + | UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC + | UOTGHS_HSTICR_RXRSMIC; + + otg_ack_vbus_transition(); + + // Enable Vbus change and error interrupts + // Disable automatic Vbus control after Vbus error + Set_bits(UOTGHS->UOTGHS_CTRL, + UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE); + + uhd_enable_vbus(); + + // Force Vbus interrupt when Vbus is always high + // This is possible due to a short timing between a Host mode stop/start. + if (Is_otg_vbus_high()) + { + otg_raise_vbus_transition(); + } + + // Enable main control interrupt + // Connection, SOF and reset + UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC;// | UOTGHS_HSTICR_RSTIC;// | UOTGHS_HSTICR_HSOFIC; + + otg_freeze_clock(); + + uhd_state = UHD_STATE_NO_VBUS; + + cpu_irq_restore(flags); +} + +void UHD_BusReset(void) +{ + uhd_start_reset(); +} + +uhd_vbus_state_t UHD_GetVBUSState(void) +{ + return uhd_state; +} + +/*uhd_speed_t uhd_get_speed(void) +{ + switch (uhd_get_speed_mode()) + { + case UOTGHS_SR_SPEED_HIGH_SPEED: + return UHD_SPEED_HIGH; + + case UOTGHS_SR_SPEED_FULL_SPEED: + return UHD_SPEED_FULL; + + case UOTGHS_SR_SPEED_LOW_SPEED: + return UHD_SPEED_LOW; + + default: + return UHD_SPEED_LOW; + } +}*/ + +/** + * \brief Allocate FIFO for pipe 0. + * + * \param ul_add Address of remote device for pipe 0. + * \param ul_ep_size Actual size of the FIFO in bytes. + * + * \retval 0 success. + * \retval 1 error. + */ +uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size) +{ + if (ul_ep_size < 8) + { + TRACE_UOTGHS(printf("/!\\ UHD_EP0_Alloc : incorrect pipe size!\r\n");) + return 1; + } + + if (Is_uhd_pipe_enabled(0)) + { + // Pipe is already allocated + return 0; + } + + uhd_enable_pipe(0); + uhd_configure_pipe(0, // Pipe 0 + 0, // No frequency + 0, // Enpoint 0 + UOTGHS_HSTPIPCFG_PTYPE_CTRL, + UOTGHS_HSTPIPCFG_PTOKEN_SETUP, + ul_ep_size, + UOTGHS_HSTPIPCFG_PBK_1_BANK, 0); + + uhd_allocate_memory(0); + + if (!Is_uhd_pipe_configured(0)) + { + TRACE_UOTGHS(printf("/!\\ UHD_EP0_Alloc : incorrect pipe settings!\r\n");) + uhd_disable_pipe(0); + return 1; + } + + uhd_configure_address(0, ul_add); + + // Always enable stall and error interrupts of control endpoint + /*uhd_enable_stall_interrupt(0); + uhd_enable_pipe_error_interrupt(0); + uhd_enable_pipe_interrupt(0);*/ + return 0; +} + +void UHD_EP_Free(uint32_t add, uint32_t endp) +{ + // Search endpoint(s) in all pipes + for (uint8_t pipe = 0; pipe < UOTGHS_EPT_NUM; pipe++) + { + if (!Is_uhd_pipe_enabled(pipe)) + { + continue; + } + + if (add != uhd_get_configured_address(pipe)) + { + continue; + } + + /* if (endp != 0xFF) + { + // Disable specific endpoint number + if (endp != uhd_get_pipe_endpoint_address(pipe)) + { + continue; // Mismatch + } + } +*/ + // Unalloc pipe + uhd_disable_pipe(pipe); + uhd_unallocate_memory(pipe); + uhd_reset_pipe(pipe); + } +} + +uint32_t UHD_EP_Read(uint32_t ul_ep, uint32_t ul_size, uint8_t* data) +{ + uint8_t *ptr_ep_data = 0; + uint8_t nb_byte_received = 0; + uint32_t ul_nb_trans = 0; + + // Get information to read data + nb_byte_received = uhd_byte_count(ul_ep); + + ptr_ep_data = (uint8_t *) & uhd_get_pipe_fifo_access(ul_ep, 8); + + // Copy data from pipe to payload buffer + while (ul_size && nb_byte_received) { + *data++ = *ptr_ep_data++; + ul_nb_trans++; + ul_size--; + nb_byte_received--; + } + + return ul_nb_trans; +} + +void UHD_EP_Write(uint32_t ul_ep, uint32_t ul_size, uint8_t* data) +{ + volatile uint8_t *ptr_ep_data = 0; + uint32_t i = 0; + + // Check pipe + if (!Is_uhd_pipe_enabled(ul_ep)) + { + // Endpoint not valid + TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");) + return; + } + + ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_ep, 8); + for (i = 0; i < ul_size; ++i) + *ptr_ep_data++ = *data++; +} + +void UHD_EP_Send(uint32_t ul_ep, uint32_t ul_token_type) +{ + // Check pipe + if (!Is_uhd_pipe_enabled(ul_ep)) + { + // Endpoint not valid + TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");) + return; + } + + // Set token type + uhd_configure_pipe_token(ul_ep, ul_token_type); + + // Clear interrupt flags + uhd_ack_setup_ready(ul_ep); + uhd_ack_in_received(ul_ep); + uhd_ack_out_ready(ul_ep); + uhd_ack_short_packet(ul_ep); + + // Send actual packet + uhd_ack_fifocon(ul_ep); + uhd_unfreeze_pipe(ul_ep); +} + +/** + * \brief Check is transfer is complete. + * + * \param ul_add Address of remote device for pipe 0. + * \param ul_ep_size Actual size of the FIFO in bytes. + * + * \retval 0 transfer is not complete. + * \retval 1 transfer is complete. + */ +uint32_t UHD_EP_Is_Transfer_Complete(uint32_t ul_ep, uint32_t ul_token_type) +{ + // Check for transfer completion depending on token type + switch (ul_token_type) + { + case UOTGHS_HSTPIPCFG_PTOKEN_SETUP: + if (Is_uhd_setup_ready(ul_ep)) + { + uhd_freeze_pipe(ul_ep); + uhd_ack_setup_ready(ul_ep); + return 1; + } + + case UOTGHS_HSTPIPCFG_PTOKEN_IN: + if (Is_uhd_in_received(ul_ep)) + { + // In case of low USB speed and with a high CPU frequency, + // a ACK from host can be always running on USB line + // then wait end of ACK on IN pipe. + while(!Is_uhd_pipe_frozen(ul_ep)) + ; + + // IN packet received + uhd_ack_in_received(ul_ep); + + return 1; + } + + case UOTGHS_HSTPIPCFG_PTOKEN_OUT: + if (Is_uhd_out_ready(ul_ep)) + { + // OUT packet sent + uhd_freeze_pipe(ul_ep); + uhd_ack_out_ready(ul_ep); + + return 1; + } + } + + // Nothing to report + return 0; +} + +#endif /* SAM3XA_SERIES */ diff --git a/hardware/arduino/sam/variants/arduino_due_x/build_gcc/libvariant_arduino_due_x.mk b/hardware/arduino/sam/variants/arduino_due_x/build_gcc/libvariant_arduino_due_x.mk index cd836513e..3f8b1b760 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/build_gcc/libvariant_arduino_due_x.mk +++ b/hardware/arduino/sam/variants/arduino_due_x/build_gcc/libvariant_arduino_due_x.mk @@ -58,6 +58,7 @@ INCLUDES += -I$(ARDUINO_PATH) INCLUDES += -I$(ARDUINO_PATH)/USB INCLUDES += -I$(SYSTEM_PATH) INCLUDES += -I$(SYSTEM_PATH)/libsam +INCLUDES += -I$(SYSTEM_PATH)/USBHost INCLUDES += -I$(VARIANT_BASE_PATH) INCLUDES += -I$(VARIANT_PATH) INCLUDES += -I$(CMSIS_ARM_PATH) diff --git a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a index 00960209f..baaae2e54 100644 Binary files a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a and b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a differ diff --git a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt index 7447be8ba..0742e34b0 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt +++ b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt @@ -99,14 +99,14 @@ pwmc.o: 00000000 T PWMC_SetSyncChannelUpdateUnlock 00000000 T PWMC_WriteBuffer U __assert_func -00000000 r __func__.3192 -00000000 r __func__.3203 -00000000 r __func__.3218 -00000000 r __func__.3229 -00000000 r __func__.3240 -00000000 r __func__.3247 -00000000 r __func__.3331 -00000000 r __func__.3337 +00000000 r __func__.3227 +00000000 r __func__.3238 +00000000 r __func__.3253 +00000000 r __func__.3264 +00000000 r __func__.3275 +00000000 r __func__.3282 +00000000 r __func__.3366 +00000000 r __func__.3372 rtc.o: 00000000 T RTC_ClearSCCR @@ -122,9 +122,9 @@ rtc.o: 00000000 T RTC_SetTime 00000000 T RTC_SetTimeAlarm U __assert_func -00000000 r __func__.3189 -00000000 r __func__.3198 -00000000 r __func__.3203 +00000000 r __func__.3224 +00000000 r __func__.3233 +00000000 r __func__.3238 rtt.o: 00000000 T RTT_EnableIT @@ -133,8 +133,8 @@ rtt.o: 00000000 T RTT_SetAlarm 00000000 T RTT_SetPrescaler U __assert_func -00000000 r __func__.3196 -00000000 r __func__.3204 +00000000 r __func__.3231 +00000000 r __func__.3239 spi.o: 00000000 T SPI_Configure @@ -155,9 +155,9 @@ tc.o: 00000000 T TC_Start 00000000 T TC_Stop U __assert_func -00000000 r __func__.3191 -00000000 r __func__.3197 -00000000 r __func__.3203 +00000000 r __func__.3226 +00000000 r __func__.3232 +00000000 r __func__.3238 timetick.o: 00000000 T GetTickCount @@ -184,18 +184,18 @@ twi.o: 00000000 T TWI_TransferComplete 00000000 T TWI_WriteByte U __assert_func -00000000 r __func__.3556 -00000000 r __func__.3571 -00000000 r __func__.3575 -00000000 r __func__.3582 -00000000 r __func__.3586 00000000 r __func__.3591 -00000000 r __func__.3599 -00000000 r __func__.3613 -00000000 r __func__.3618 -00000000 r __func__.3622 -00000000 r __func__.3627 -00000000 r __func__.3631 +00000000 r __func__.3606 +00000000 r __func__.3610 +00000000 r __func__.3617 +00000000 r __func__.3621 +00000000 r __func__.3626 +00000000 r __func__.3634 +00000000 r __func__.3648 +00000000 r __func__.3653 +00000000 r __func__.3657 +00000000 r __func__.3662 +00000000 r __func__.3666 usart.o: 00000000 T USART_Configure @@ -214,7 +214,7 @@ usart.o: 00000000 T USART_Write 00000000 T USART_WriteBuffer U __assert_func -00000000 r __func__.3477 +00000000 r __func__.3512 wdt.o: 00000000 T WDT_Disable @@ -343,6 +343,13 @@ udp.o: udphs.o: uotghs.o: +00000000 T UOTGHS_Handler +00000000 B gpf_isr + +interrupt_sam_nvic.o: +00000000 D g_interrupt_enabled + +uotghs_device.o: 00000000 T UDD_Attach 00000000 T UDD_ClearIN 00000000 T UDD_ClearOUT @@ -367,9 +374,8 @@ uotghs.o: 00000000 T UDD_WaitForINOrOUT 00000000 T UDD_WaitIN 00000000 T UDD_WaitOUT -00000000 T UOTGHS_Handler U g_interrupt_enabled -00000000 b gpf_isr + U gpf_isr U pmc_enable_periph_clk U pmc_enable_udpck U pmc_enable_upll_clock @@ -377,5 +383,23 @@ uotghs.o: 00000000 b ul_recv_fifo_ptr 00000000 b ul_send_fifo_ptr -interrupt_sam_nvic.o: -00000000 D g_interrupt_enabled +uotghs_host.o: +00000000 T UHD_BusReset +00000000 T UHD_EP0_Alloc +00000000 T UHD_EP_Free +00000000 T UHD_EP_Is_Transfer_Complete +00000000 T UHD_EP_Read +00000000 T UHD_EP_Send +00000000 T UHD_EP_Write +00000000 T UHD_GetVBUSState +00000000 t UHD_ISR +00000000 T UHD_Init +00000000 T UHD_SetStack + U g_interrupt_enabled + U gpf_isr + U iprintf + U pmc_enable_periph_clk + U pmc_enable_udpck + U pmc_enable_upll_clock + U pmc_switch_udpck_to_upllck +00000000 b uhd_state