mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-29 18:52:13 +01:00
[sam] USB Host stack v1 with enumeration working okay using validation example
This commit is contained in:
parent
b99d525a91
commit
bc62c81396
@ -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
|
||||
|
@ -540,7 +540,7 @@ uint32_t USBD_Connected(void)
|
||||
//=======================================================================
|
||||
//=======================================================================
|
||||
|
||||
USB_ USB;
|
||||
//USB_ USB;
|
||||
|
||||
USB_::USB_()
|
||||
{
|
||||
|
@ -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)))
|
||||
|
||||
|
Binary file not shown.
@ -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
|
@ -40,7 +40,7 @@ int main( void )
|
||||
delay(1);
|
||||
|
||||
#if defined(USBCON)
|
||||
USB.attach();
|
||||
//USB.attach();
|
||||
#endif
|
||||
|
||||
setup();
|
||||
|
@ -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 $@
|
||||
|
@ -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
|
@ -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)
|
@ -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
|
@ -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)
|
||||
|
@ -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_
|
@ -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 <stdio.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
//{
|
||||
//
|
||||
//
|
||||
//}
|
@ -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 <Spi.h>
|
||||
//#include <WProgram.h>
|
||||
#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_
|
@ -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_
|
@ -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 <stdio.h>
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 <Max3421e.h>
|
||||
#include <stdint.h>
|
||||
#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 */
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef _ch9_h_
|
||||
#define _ch9_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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_
|
||||
|
@ -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_ */
|
||||
|
@ -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 <stdint.h>
|
||||
|
||||
@ -403,4 +403,4 @@ typedef uint32_t iram_size_t;
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* _USB_DRIVER_*/
|
||||
#endif /* USB_DEVICE_H_INCLUDED */
|
||||
|
59
hardware/arduino/sam/system/libsam/include/USB_host.h
Normal file
59
hardware/arduino/sam/system/libsam/include/USB_host.h
Normal file
@ -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 <stdint.h>
|
||||
|
||||
#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 */
|
@ -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 */
|
378
hardware/arduino/sam/system/libsam/include/uotghs_host.h
Normal file
378
hardware/arduino/sam/system/libsam/include/uotghs_host.h
Normal file
@ -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_HSTPIPCFG_PSIZE_Pos)&UOTGHS_HSTPIPCFG_PSIZE_Msk)|\
|
||||
(((token)<<UOTGHS_HSTPIPCFG_PTOKEN_Pos)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
|
||||
(((type)<<UOTGHS_HSTPIPCFG_PTYPE_Pos)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
|
||||
(((ep_num)<<UOTGHS_HSTPIPCFG_PEPNUM_Pos)&UOTGHS_HSTPIPCFG_PEPNUM_Msk)|\
|
||||
bank_switch |\
|
||||
(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk)))
|
||||
|
||||
#define Is_uhd_pipe_configured(p) (Tst_bits(UOTGHS->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 */
|
@ -17,22 +17,10 @@
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#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 */
|
||||
|
324
hardware/arduino/sam/system/libsam/source/uotghs_device.c
Normal file
324
hardware/arduino/sam/system/libsam/source/uotghs_device.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#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 */
|
404
hardware/arduino/sam/system/libsam/source/uotghs_host.c
Normal file
404
hardware/arduino/sam/system/libsam/source/uotghs_host.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#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 */
|
@ -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)
|
||||
|
Binary file not shown.
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user