@ -0,0 +1 @@ | |||
build |
@ -0,0 +1,75 @@ | |||
TOOLCHAIN = /opt/arm-toolchain | |||
OPENOCD = /opt/arm-toolchain/openocd | |||
AS = $(TOOLCHAIN)/bin/arm-elf-as | |||
CC = $(TOOLCHAIN)/bin/arm-elf-gcc | |||
LD = $(TOOLCHAIN)/bin/arm-elf-ld | |||
NM = $(TOOLCHAIN)/bin/arm-elf-nm | |||
SIZE = $(TOOLCHAIN)/bin/arm-elf-size | |||
OBJCOPY = $(TOOLCHAIN)/bin/arm-elf-objcopy | |||
OBJDUMP = $(TOOLCHAIN)/bin/arm-elf-objdump | |||
INCDIRS = include $(TOOLCHAIN)/lib/gcc/arm-elf/4.1.1/include $(TOOLCHAIN)/arm-elf/include | |||
LIBDIRS = $(TOOLCHAIN)/arm-elf/lib $(TOOLCHAIN)/lib/gcc/arm-elf/4.1.1 | |||
# ------ | |||
BUILD = build | |||
TARGET = sam7fc | |||
ASFLAGS = -mcpu=arm7tdmi -Wa,-adhlns=$(BUILD)/$(*D)/$(*F).lst,--gdwarf-2 -Iinclude | |||
CFLAGS = -gdwarf-2 -mcpu=arm7tdmi -Os -std=gnu99 | |||
CFLAGS += -Wa,-adhlns=$(BUILD)/$(*D)/$(*F).lst | |||
CFLAGS += -nostdinc $(patsubst %,-I%,$(INCDIRS)) | |||
CFLAGS += -MD -MP -MF $(BUILD)/.dep/$(*F).d | |||
CFLAGS += -Wall | |||
#CFLAGS += -Wextra | |||
#CFLAGS += -Wcast-align -Wimplicit -Wunused | |||
#CFLAGS += -Wpointer-arith -Wswitch | |||
#CFLAGS += -Wredundant-decls -Wreturn-type -Wshadow | |||
#CFLAGS += -Wbad-function-cast -Wsign-compare -Waggregate-return | |||
#CFLAGS += -Wcast-qual -Wnested-externs | |||
#CFLAGS += -Wmissing-prototypes | |||
#CFLAGS += -Wstrict-prototypes -Wmissing-declarations | |||
LDFLAGS = -nostartfiles -t ldscript.ld -Wl,-Map=$@.map,--cref | |||
LDFLAGS += $(patsubst %,-L%,$(LIBDIRS)) | |||
LDFLAGS += -lc -lgcc | |||
# ------ | |||
SRC := $(wildcard *.c) $(wildcard src/*.c) $(wildcard src/*/*.c) | |||
AS_SRC := $(wildcard *.s) $(wildcard src/*.s) | |||
all: $(BUILD)/$(TARGET).elf | |||
@$(SIZE) -x $< | |||
$(BUILD)/$(TARGET).elf: $(patsubst %,$(BUILD)/%,$(AS_SRC:.s=.o) $(SRC:.c=.o)) | |||
@echo " Linking file: $@" | |||
@$(shell mkdir -p $(BUILD)/$(*D)) | |||
@$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) | |||
@$(OBJCOPY) -O binary $@ $@.bin | |||
@$(OBJCOPY) -O ihex $@ $@.hex | |||
@$(OBJDUMP) -h -S -C $@ > $@.lss | |||
@$(NM) -n $@ > $@.sym | |||
$(BUILD)/%.o: %.c | |||
@echo " Building file: $<" | |||
@$(shell mkdir -p $(BUILD)/$(*D)) | |||
@$(CC) -c $(CFLAGS) $< -o $@ | |||
$(BUILD)/%.o: %.s | |||
@echo " Building file: $<" | |||
@$(shell mkdir -p $(BUILD)/$(*D)) | |||
@$(CC) -c $(ASFLAGS) $< -o $@ | |||
clean: | |||
rm -rf $(BUILD) | |||
openocd: | |||
$(shell $(OPENOCD) -f scripts/openocd.cfg) | |||
-include $(shell mkdir -p $(BUILD)/.dep 2> /dev/null) $(wildcard $(BUILD)/.dep/*.d) |
@ -0,0 +1,244 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 01/2008 by Olaf Rempel * | |||
* razzor@kopf-tisch.de * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; version 2 of the License * | |||
* * | |||
* This program 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 General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
.equ AIC_IVR, (256) | |||
.equ AIC_FVR, (260) | |||
.equ AIC_EOICR, (304) | |||
.equ AT91C_BASE_AIC, (0xFFFFF000) | |||
.equ IRQ_Stack_Size, (3 * 8 * 4) | |||
.equ FIQ_Stack_Size, (3 * 8 * 4) | |||
.equ ABT_Stack_Size, 192 | |||
.equ ARM_MODE_FIQ, 0x11 | |||
.equ ARM_MODE_IRQ, 0x12 | |||
.equ ARM_MODE_SVC, 0x13 | |||
.equ ARM_MODE_ABT, 0x17 | |||
.equ I_BIT, 0x80 | |||
.equ F_BIT, 0x40 | |||
.section .text | |||
.global _start | |||
.func _start | |||
_start: ldr pc, [pc, #24] /* 0x00 Reset handler */ | |||
undefvec: ldr pc, [pc, #24] /* 0x04 Undefined Instruction */ | |||
swivec: ldr pc, [pc, #24] /* 0x08 Software Interrupt */ | |||
pabtvec: ldr pc, [pc, #24] /* 0x0C Prefetch Abort */ | |||
dabtvec: ldr pc, [pc, #24] /* 0x10 Data Abort */ | |||
rsvdvec: ldr pc, [pc, #24] /* 0x14 reserved */ | |||
irqvec: ldr pc, [pc, #24] /* 0x18 IRQ */ | |||
fiqvec: ldr pc, [pc, #24] /* 0x1c FIQ */ | |||
/* 0x80000000 will result in Prefetch Abort */ | |||
.word InitReset | |||
.word 0x80000000 | |||
.word 0x80000000 | |||
.word ABT_Handler_Entry | |||
.word ABT_Handler_Entry | |||
.word 0x80000000 | |||
.word IRQ_Handler_Entry | |||
.word FIQ_Handler_Entry | |||
.endfunc | |||
.global InitReset | |||
.func InitReset | |||
InitReset: | |||
.extern at91_init1 | |||
/* Call Low level init function */ | |||
ldr sp,=__stack_top__ | |||
ldr r0,=at91_init1 | |||
mov lr, pc | |||
bx r0 | |||
mov r0, sp | |||
/* Setup FIQ Mode Stack */ | |||
msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT | |||
mov sp, r0 | |||
sub r0, r0, #FIQ_Stack_Size | |||
/* store AIC Base in ARM_MODE_FIQ:r8 for faster access */ | |||
ldr r8, =AT91C_BASE_AIC | |||
/* Setup IRQ Mode Stack */ | |||
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT | |||
mov sp, r0 | |||
sub r0, r0, #IRQ_Stack_Size | |||
/* Setup Abort Mode Stack */ | |||
msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT | |||
mov sp, r0 | |||
sub r0, r0, #ABT_Stack_Size | |||
/* Setup Supervisor Mode Stack (IRQ & NMI enabled) */ | |||
msr CPSR_c, #ARM_MODE_SVC | |||
mov sp, r0 | |||
/* Relocate .data section */ | |||
ldr r1, =__text_end__ | |||
ldr r2, =__data_start__ | |||
ldr r3, =__data_end__ | |||
LoopRel: cmp r2, r3 | |||
ldrlo r0, [r1], #4 | |||
strlo r0, [r2], #4 | |||
blo LoopRel | |||
/* Clear .bss section */ | |||
mov r0, #0 | |||
ldr r1, =__bss_start__ | |||
ldr r2, =__bss_end__ | |||
LoopZI: cmp r1, r2 | |||
strlo r0, [r1], #4 | |||
BLO LoopZI | |||
/* Start main() */ | |||
ldr lr,=exit | |||
ldr r0,=main | |||
bx r0 | |||
.endfunc | |||
.global exit | |||
.func exit | |||
/* exit dummy for newlib */ | |||
exit: b . | |||
.endfunc | |||
.global ABT_Handler_Entry | |||
.func ABT_Handler_Entry | |||
ABT_Handler_Entry: | |||
/* disable interrupts (F_BIT not set on entry) */ | |||
msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT | |||
/* store all registers */ | |||
stmfd sp!, { r0-r12 } | |||
/* saved cpsr (from aborted mode) */ | |||
mrs r0, SPSR | |||
/* address of abort (pc) */ | |||
mov r3, lr | |||
/* enter previous mode and get lr(r14), sp(r13) */ | |||
/* TODO: interrupts might be enabled? */ | |||
/* TODO: thumb mode enabled? */ | |||
msr CPSR_c, r0 | |||
mov r1, sp | |||
mov r2, lr | |||
/* return to abort mode */ | |||
msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT | |||
/* store remaining registers (r1-r3 == r13-r15) */ | |||
stmfd sp!, { r1-r3 } | |||
mov r1, sp | |||
/* execute C Handler (cpsr, registers) */ | |||
ldr r5,=at91_abt_handler | |||
mov lr, pc | |||
bx r5 | |||
b . | |||
.endfunc | |||
.global FIQ_Handler_Entry | |||
.func FIQ_Handler_Entry | |||
FIQ_Handler_Entry: | |||
/* Save r0 to ARM_MODE_FIQ:r9 */ | |||
mov r9,r0 | |||
/* get FIQ Vector from AIC and thus clear FIQ */ | |||
ldr r0 , [r8, #AIC_FVR] | |||
/* Switch to ARM_MODE_SVC and save registers there */ | |||
msr CPSR_c,#ARM_MODE_SVC | I_BIT | F_BIT | |||
stmfd sp!, { r1-r3, r12, lr} | |||
/* execute FIQ in SVC_MODE */ | |||
mov r14, pc | |||
bx r0 | |||
/* restore registers and switch back to ARM_MODE_FIQ */ | |||
ldmia sp!, { r1-r3, r12, lr} | |||
msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT | |||
/* restore the ARM_MODE_SVC:r0 */ | |||
mov r0,r9 | |||
/* restore PC using the LR_fiq directly */ | |||
subs pc,lr,#4 | |||
.endfunc | |||
.global IRQ_Handler_Entry | |||
.func IRQ_Handler_Entry | |||
IRQ_Handler_Entry: | |||
/*- Manage Exception Entry */ | |||
/*- Adjust and save LR_irq in IRQ stack */ | |||
sub lr, lr, #4 | |||
stmfd sp!, {lr} | |||
/*- Save SPSR need to be saved for nested interrupt */ | |||
mrs r14, SPSR | |||
stmfd sp!, {r14} | |||
/*- Save and r0 in IRQ stack */ | |||
stmfd sp!, {r0} | |||
/*- Write in the IVR to support Protect Mode */ | |||
/*- No effect in Normal Mode */ | |||
/*- De-assert the NIRQ and clear the source in Protect Mode */ | |||
ldr r14, =AT91C_BASE_AIC | |||
ldr r0 , [r14, #AIC_IVR] | |||
str r14, [r14, #AIC_IVR] | |||
/*- Enable Interrupt and Switch in Supervisor Mode */ | |||
msr CPSR_c, #ARM_MODE_SVC | |||
/*- Save scratch/used registers and LR in User Stack */ | |||
stmfd sp!, { r1-r3, r12, r14} | |||
/*- Branch to the routine pointed by the AIC_IVR */ | |||
mov r14, pc | |||
bx r0 | |||
/*- Restore scratch/used registers and LR from User Stack*/ | |||
ldmia sp!, { r1-r3, r12, r14} | |||
/*- Disable Interrupt and switch back in IRQ mode */ | |||
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | |||
/*- Mark the End of Interrupt on the AIC */ | |||
ldr r14, =AT91C_BASE_AIC | |||
str r14, [r14, #AIC_EOICR] | |||
/*- Restore SPSR_irq and r0 from IRQ stack */ | |||
ldmia sp!, {r0} | |||
/*- Restore SPSR_irq and r0 from IRQ stack */ | |||
ldmia sp!, {r14} | |||
msr SPSR_cxsf, r14 | |||
/*- Restore adjusted LR_irq from IRQ stack directly in the PC */ | |||
ldmia sp!, {pc}^ | |||
.endfunc | |||
.end |
@ -0,0 +1,81 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 01/2008 by Olaf Rempel * | |||
* razzor@kopf-tisch.de * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; version 2 of the License * | |||
* * | |||
* This program 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 General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#include <stdint.h> | |||
#include "AT91SAM7S256.h" | |||
static void empty_isr(void) {} | |||
/* | |||
* Init critical onchip hardware: | |||
* - disable Watchdog | |||
* - enable Oscillator and PLL, switch to 48MHz MCK | |||
* - set empty Interrupt Handlers | |||
*/ | |||
void at91_init1(void) | |||
{ | |||
/* disable watchdog */ | |||
*AT91C_WDTC_WDMR = AT91C_WDTC_WDDIS; | |||
/* enable user reset */ | |||
*AT91C_RSTC_RMR = (AT91C_RSTC_KEY & 0xA5 << 24) | AT91C_RSTC_URSTEN; | |||
/* Set Flash Waitstates */ | |||
*AT91C_MC_FMR = AT91C_MC_FWS_1FWS; | |||
/* | |||
* Enable main oscillator (MAINCK) | |||
* startup time: 8*6/32768 -> 1.46ms | |||
*/ | |||
AT91S_PMC *pmc = AT91C_BASE_PMC; | |||
pmc->PMC_MOR = (AT91C_CKGR_OSCOUNT & (6<<8)) | | |||
AT91C_CKGR_MOSCEN; | |||
while (!(pmc->PMC_SR & AT91C_PMC_MOSCS)); | |||
/* | |||
* PLLCK = 18.432MHz / 24 * 125 = 96MHz -> div:24, mul:124 | |||
* startup time: 32/32768 -> 976us | |||
*/ | |||
pmc->PMC_PLLR = (AT91C_CKGR_DIV & 24) | | |||
(AT91C_CKGR_MUL & (124<<16)) | | |||
(AT91C_CKGR_PLLCOUNT & (32<<8)) ; | |||
while (!(pmc->PMC_SR & AT91C_PMC_LOCK)); | |||
/* MCK = PLLCK / 2 = 48MHz */ | |||
pmc->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | | |||
AT91C_PMC_PRES_CLK_2; | |||
while (!(pmc->PMC_SR & AT91C_PMC_MCKRDY)); | |||
/* enable protected mode (let AIC work with debugger) */ | |||
AT91S_AIC *aic = AT91C_BASE_AIC; | |||
aic->AIC_DCR = AT91C_AIC_DCR_PROT; | |||
/* Disable & clear all Interrupts */ | |||
aic->AIC_IDCR = ~0; | |||
aic->AIC_ICCR = ~0; | |||
/* default Interrupt Handlers just return */ | |||
aic->AIC_FVR = (uint32_t)empty_isr; | |||
aic->AIC_IVR = (uint32_t)empty_isr; | |||
uint32_t i; | |||
for (i = 0; i < 32; i++) { | |||
aic->AIC_SMR[i] = 0; | |||
aic->AIC_SVR[i] = (uint32_t)empty_isr; | |||
} | |||
aic->AIC_SPU = (uint32_t)empty_isr; | |||
} |
@ -0,0 +1,12 @@ | |||
#ifndef AT91_DBGU_H_ | |||
#define AT91_DBGU_H_ | |||
#include <stddef.h> | |||
void at91_dbgu_init(void); | |||
void at91_dbgu_putc(char c); | |||
void at91_dbgu_puts(const char *p); | |||
int at91_dbgu_write(void *base, const char *buf, size_t len); | |||
#endif /*AT91_DBGU_H_*/ |
@ -0,0 +1,20 @@ | |||
#ifndef AT91_PIO_H_ | |||
#define AT91_PIO_H_ | |||
#include <stdint.h> | |||
struct pio_pinchange_isr { | |||
uint32_t mask; | |||
void (*func)(uint32_t status, uint32_t input); | |||
}; | |||
#define PIO_PINCHANGE_ISR(mask, func) \ | |||
static struct pio_pinchange_isr \ | |||
__attribute__((used, section(".pio_isr"))) \ | |||
pio_isr_##func = { mask, &func }; | |||
void pio_trigger_isr(uint32_t mask); | |||
void at91_pio_init(void); | |||
#endif /*AT91_PIO_H_*/ |
@ -0,0 +1,25 @@ | |||
#ifndef AT91_PITC_H_ | |||
#define AT91_PITC_H_ | |||
#include <stdint.h> | |||
#include <stddef.h> | |||
#include "list.h" | |||
#define PITC_RESTART_TIMER 0 | |||
#define PITC_REMOVE_TIMER 1 | |||
struct pitc_timer { | |||
struct list_head list; | |||
uint32_t interval; | |||
uint32_t nextrun; | |||
uint32_t (*func)(struct pitc_timer *); | |||
void *privdata; | |||
}; | |||
void pitc_schedule_timer(struct pitc_timer *timer); | |||
struct pitc_timer * alloc_pitc_timer(uint32_t interval, uint32_t (*func)(struct pitc_timer *), void *privdata); | |||
uint32_t pitc_get_ticks(void); | |||
void at91_pitc_init(void); | |||
#endif /*AT91_PITC_H_*/ |
@ -0,0 +1,22 @@ | |||
#ifndef AT91_SYSC_H_ | |||
#define AT91_SYSC_H_ | |||
#include <stdint.h> | |||
enum syscirqs { | |||
AT91_SYSIRQ_PIT = 0, | |||
AT91_SYSIRQ_DBGU = 1, | |||
AT91_SYSIRQ_EFC = 2, | |||
AT91_SYSIRQ_WDT = 3, | |||
AT91_SYSIRQ_RTT = 4, | |||
AT91_SYSIRQ_RSTC = 5, | |||
AT91_SYSIRQ_PMC = 6, | |||
AT91_SYSIRQ_COUNT | |||
}; | |||
typedef void SYSCISR(uint32_t status); | |||
void at91_sysc_init(void); | |||
void sysc_register_isr(enum syscirqs irq, SYSCISR *isr); | |||
#endif /*AT91_SYSC_H_*/ |
@ -0,0 +1,14 @@ | |||
#ifndef RC_PPM_H_ | |||
#define RC_PPM_H_ | |||
#define MAX_CHANNELS 8 | |||
struct rc_values { | |||
int16_t ch[MAX_CHANNELS]; | |||
uint32_t count; | |||
}; | |||
void at91_tc1_init(void); | |||
uint32_t rc_ppm_getvalues(struct rc_values *rc); | |||
#endif /*RC_PPM_H_*/ |
@ -0,0 +1,9 @@ | |||
#ifndef AT91_TESTS_H_ | |||
#define AT91_TESTS_H_ | |||
void at91_rttc_test_init(void); | |||
void at91_adc_test_init(void); | |||
void at91_adc_printresults(void); | |||
#endif /*AT91_TESTS_H_*/ |
@ -0,0 +1,57 @@ | |||
#ifndef AT91TWI_H_ | |||
#define AT91TWI_H_ | |||
#include <list.h> | |||
/* TWI slave addresses */ | |||
#define TWI_ADDR_BL1 0x21 | |||
#define TWI_ADDR_BL2 0x22 | |||
#define TWI_ADDR_BL3 0x23 | |||
#define TWI_ADDR_BL4 0x24 | |||
#define TWI_ADDR_EEPROM 0x40 | |||
/* TWIBOOT commands */ | |||
#define CMD_WAIT 0x00 | |||
#define CMD_GET_INFO 0x10 | |||
#define CMD_GET_SIGNATURE 0x11 | |||
#define CMD_WRITE_FLASH 0x12 | |||
#define CMD_READ_FLASH 0x13 | |||
#define CMD_WRITE_EEPROM 0x14 | |||
#define CMD_READ_EEPROM 0x15 | |||
#define CMD_BOOT_APPLICATION 0x1F | |||
/* blctrl commands */ | |||
//#define CMD_WAIT 0x00 | |||
//#define CMD_GET_INFO 0x10 | |||
#define CMD_SET_PWM 0x21 | |||
#define CMD_GET_STATUS 0x22 | |||
//#define CMD_SET_PARAM 0x23 | |||
//#define CMD_GET_PARAM 0x24 | |||
#define CMD_BOOT_LOADER 0x2F | |||
struct blmc_cmd { | |||
uint32_t cmd; /* cmd byte(s) */ | |||
uint8_t mode; /* read/write, cmdlen (1-3 bytes) */ | |||
uint8_t size; /* data size */ | |||
uint8_t *data; /* read/write data */ | |||
}; | |||
/* same bits as TWI_MMR[8..15] */ | |||
#define BLMC_CMD_READ 0x10 | |||
#define BLMC_CMD_WRITE 0x00 | |||
#define BLMC_CMD_0_ARG 0x01 | |||
#define BLMC_CMD_1_ARG 0x02 | |||
#define BLMC_CMD_2_ARG 0x03 | |||
uint32_t twi_read_eeprom(uint32_t addr, uint8_t *buf, uint32_t size); | |||
uint32_t twi_write_eeprom(uint32_t addr, uint8_t *buf, uint32_t size); | |||
uint32_t twi_setpwm(uint8_t *values); | |||
uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd); | |||
void at91_twi_init(void); | |||
void at91_twi_test(void); | |||
#endif /*AT91TWI_H_*/ |
@ -0,0 +1,6 @@ | |||
#ifndef AT91_UDP_H_ | |||
#define AT91_UDP_H_ | |||
void at91_udp_init(void); | |||
#endif /*AT91_UDP_H_*/ |
@ -0,0 +1,26 @@ | |||
#ifndef ATOMIC_H_ | |||
#define ATOMIC_H_ | |||
//TODO: not for thumbcode?! | |||
#define disable_irqs() \ | |||
{ \ | |||
int temp_; \ | |||
asm volatile ( \ | |||
"mrs %0, cpsr" "\n\t" \ | |||
"stmfd sp!, {%0}" "\n\t" \ | |||
"orr %0, %0, #0xC0" "\n\t" \ | |||
"msr cpsr, %0" "\n\t" \ | |||
: "=r" (temp_) : ); \ | |||
} | |||
#define restore_irqs() \ | |||
{ \ | |||
int temp_; \ | |||
asm volatile ( \ | |||
"ldmfd sp!, {%0}" "\n\t" \ | |||
"msr cpsr, %0" "\n\t" \ | |||
: "=r" (temp_) : ); \ | |||
} | |||
#endif /*ATOMIC_H_*/ |
@ -0,0 +1,43 @@ | |||
#ifndef BOARD_H_ | |||
#define BOARD_H_ | |||
#include "AT91SAM7S256.h" | |||
/* keep in sync with at91_init1.c */ | |||
#define MAINCK 18432000 | |||
#define PLLCK (MAINCK / 24 * 125) /* 96MHz */ | |||
#define MCK (PLLCK / 2) /* 48MHz */ | |||
/* DBGU UART Baudrate calculation */ | |||
#define BAUD_TO_DIV(BAUD) (MCK / (16 * BAUD)) | |||
/* LED PIOs */ | |||
#define LED_ORANGE AT91C_PIO_PA17 | |||
#define LED_GREEN AT91C_PIO_PA18 | |||
/* Taster PIOs */ | |||
#define TAST1 AT91C_PIO_PA19 | |||
#define TAST2 AT91C_PIO_PA20 | |||
/* USB PIOs */ | |||
#define UDP_VBUS_MON AT91C_PIO_PA24 | |||
#define UDP_PULLUP AT91C_PIO_PA25 | |||
/* ATMEL IDs */ | |||
#define USB_VENDOR_ID 0x03EB | |||
#define USB_PRODUCT_ID 0x6124 | |||
/* Interrupt Priorities (7 = highest) */ | |||
#define IRQPRIO_SYSC 6 /* pitc */ | |||
#define IRQPRIO_PIOA 1 /* pinchange interrupts */ | |||
#define IRQPRIO_ADC 2 | |||
#define IRQPRIO_TWI 7 /* twi must be fast! */ | |||
#define IRQPRIO_UDP 4 /* usb */ | |||
#define IRQPRIO_TC1 5 /* ppm capturing */ | |||
/* TODO: find better place */ | |||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) | |||
#define MIN(a,b) ((a) < (b) ? (a) : (b)) | |||
#define MAX(a,b) ((a) > (b) ? (a) : (b)) | |||
#endif /*BOARD_H_*/ |
@ -0,0 +1,28 @@ | |||
#ifndef FIFO_H_ | |||
#define FIFO_H_ | |||
#include <stdint.h> | |||
struct fifo { | |||
uint32_t in; | |||
uint32_t out; | |||
uint16_t pdc_tx; | |||
uint16_t pdc_rx; | |||
uint32_t size; | |||
char buf[0]; | |||
}; | |||
uint32_t fifo_put(struct fifo *fifo, const char *buf, uint32_t len); | |||
uint32_t fifo_get(struct fifo *fifo, char *buf, uint32_t len); | |||
uint32_t fifo_rxpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize); | |||
uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize); | |||
uint32_t fifo_putbyte(struct fifo *fifo, char c); | |||
uint32_t fifo_getbyte(struct fifo *fifo, char *p); | |||
struct fifo * fifo_alloc(uint32_t size); | |||
#endif /*FIFO_H_*/ |
@ -0,0 +1,268 @@ | |||
#ifndef _LIST_H_ | |||
#define _LIST_H_ | |||
/* | |||
* stolen from linux kernel 2.6.11 (http://kernel.org/) | |||
* linux/include/linux/stddef.h (offsetoff) | |||
* linux/include/linux/kernel.h (container_of) | |||
* linux/include/linux/list.h (*list*) | |||
* linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND) | |||
* | |||
* modified by Olaf Rempel <razzor@kopf-tisch.de> | |||
*/ | |||
//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | |||
#define container_of(ptr, type, member) ({ \ | |||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | |||
(type *)( (char *)__mptr - offsetof(type,member) );}) | |||
struct list_head { | |||
struct list_head *next, *prev; | |||
}; | |||
#define LIST_HEAD_INIT(name) { &(name), &(name) } | |||
#define LIST_HEAD(name) \ | |||
struct list_head name = LIST_HEAD_INIT(name) | |||
#define INIT_LIST_HEAD(ptr) do { \ | |||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \ | |||
} while (0) | |||
/* | |||
* Insert a new entry between two known consecutive entries. | |||
* | |||
* This is only for internal list manipulation where we know | |||
* the prev/next entries already! | |||
*/ | |||
static inline void __list_add(struct list_head *new, | |||
struct list_head *prev, | |||
struct list_head *next) | |||
{ | |||
next->prev = new; | |||
new->next = next; | |||
new->prev = prev; | |||
prev->next = new; | |||
} | |||
/* | |||
* list_add - add a new entry | |||
* @new: new entry to be added | |||
* @head: list head to add it after | |||
* | |||
* Insert a new entry after the specified head. | |||
* This is good for implementing stacks. | |||
*/ | |||
static inline void list_add(struct list_head *new, struct list_head *head) | |||
{ | |||
__list_add(new, head, head->next); | |||
} | |||
/* | |||
* list_add_tail - add a new entry | |||
* @new: new entry to be added | |||
* @head: list head to add it before | |||
* | |||
* Insert a new entry before the specified head. | |||
* This is useful for implementing queues. | |||
*/ | |||
static inline void list_add_tail(struct list_head *new, struct list_head *head) | |||
{ | |||
__list_add(new, head->prev, head); | |||
} | |||
/* | |||
* Delete a list entry by making the prev/next entries | |||
* point to each other. | |||
* | |||
* This is only for internal list manipulation where we know | |||
* the prev/next entries already! | |||
*/ | |||
static inline void __list_del(struct list_head * prev, struct list_head * next) | |||
{ | |||
next->prev = prev; | |||
prev->next = next; | |||
} | |||
/* | |||
* list_del - deletes entry from list. | |||
* @entry: the element to delete from the list. | |||
* Note: list_empty on entry does not return true after this, the entry is | |||
* in an undefined state. | |||
*/ | |||
static inline void list_del(struct list_head *entry) | |||
{ | |||
__list_del(entry->prev, entry->next); | |||
entry->next = NULL; | |||
entry->prev = NULL; | |||
} | |||
/* | |||
* list_del_init - deletes entry from list and reinitialize it. | |||
* entry: the element to delete from the list. | |||
*/ | |||
static inline void list_del_init(struct list_head *entry) | |||
{ | |||
__list_del(entry->prev, entry->next); | |||
INIT_LIST_HEAD(entry); | |||
} | |||
/* | |||
* list_move - delete from one list and add as another's head | |||
* @list: the entry to move | |||
* @head: the head that will precede our entry | |||
*/ | |||
static inline void list_move(struct list_head *list, struct list_head *head) | |||
{ | |||
__list_del(list->prev, list->next); | |||
list_add(list, head); | |||
} | |||
/* | |||
* list_move_tail - delete from one list and add as another's tail | |||
* @list: the entry to move | |||
* @head: the head that will follow our entry | |||
*/ | |||
static inline void list_move_tail(struct list_head *list, | |||
struct list_head *head) | |||
{ | |||
__list_del(list->prev, list->next); | |||
list_add_tail(list, head); | |||
} | |||
/* | |||
* list_empty - tests whether a list is empty | |||
* @head: the list to test. | |||
*/ | |||
static inline int list_empty(const struct list_head *head) | |||
{ | |||
return head->next == head; | |||
} | |||
static inline void __list_splice(struct list_head *list, | |||
struct list_head *head) | |||
{ | |||
struct list_head *first = list->next; | |||
struct list_head *last = list->prev; | |||
struct list_head *at = head->next; | |||
first->prev = head; | |||
head->next = first; | |||
last->next = at; | |||
at->prev = last; | |||
} | |||
/* | |||
* list_splice - join two lists | |||
* @list: the new list to add. | |||
* @head: the place to add it in the first list. | |||
*/ | |||
static inline void list_splice(struct list_head *list, struct list_head *head) | |||
{ | |||
if (!list_empty(list)) | |||
__list_splice(list, head); | |||
} | |||
/* | |||
* list_splice_init - join two lists and reinitialise the emptied list. | |||
* @list: the new list to add. | |||
* @head: the place to add it in the first list. | |||
* | |||
* The list at @list is reinitialised | |||
*/ | |||
static inline void list_splice_init(struct list_head *list, | |||
struct list_head *head) | |||
{ | |||
if (!list_empty(list)) { | |||
__list_splice(list, head); | |||
INIT_LIST_HEAD(list); | |||
} | |||
} | |||
/* | |||
* list_entry - get the struct for this entry | |||
* @ptr: the &struct list_head pointer. | |||
* @type: the type of the struct this is embedded in. | |||
* @member: the name of the list_struct within the struct. | |||
*/ | |||
#define list_entry(ptr, type, member) \ | |||
container_of(ptr, type, member) | |||
/* | |||
* list_for_each - iterate over a list | |||
* @pos: the &struct list_head to use as a loop counter. | |||
* @head: the head for your list. | |||
*/ | |||
#define list_for_each(pos, head) \ | |||
for (pos = (head)->next; pos != (head); pos = pos->next) | |||
/* | |||
* list_for_each_prev - iterate over a list backwards | |||
* @pos: the &struct list_head to use as a loop counter. | |||
* @head: the head for your list. | |||
*/ | |||
#define list_for_each_prev(pos, head) \ | |||
for (pos = (head)->prev; pos != (head); pos = pos->prev) | |||
/* | |||
* list_for_each_safe - iterate over a list safe against removal of list entry | |||
* @pos: the &struct list_head to use as a loop counter. | |||
* @n: another &struct list_head to use as temporary storage | |||
* @head: the head for your list. | |||
*/ | |||
#define list_for_each_safe(pos, n, head) \ | |||
for (pos = (head)->next, n = pos->next; pos != (head); \ | |||
pos = n, n = pos->next) | |||
/* | |||
* list_for_each_entry - iterate over list of given type | |||
* @pos: the type * to use as a loop counter. | |||
* @head: the head for your list. | |||
* @member: the name of the list_struct within the struct. | |||
*/ | |||
#define list_for_each_entry(pos, head, member) \ | |||
for (pos = list_entry((head)->next, typeof(*pos), member); \ | |||
&pos->member != (head); \ | |||
pos = list_entry(pos->member.next, typeof(*pos), member)) | |||
/* | |||
* list_for_each_entry_reverse - iterate backwards over list of given type. | |||
* @pos: the type * to use as a loop counter. | |||
* @head: the head for your list. | |||
* @member: the name of the list_struct within the struct. | |||
*/ | |||
#define list_for_each_entry_reverse(pos, head, member) \ | |||
for (pos = list_entry((head)->prev, typeof(*pos), member); \ | |||
&pos->member != (head); \ | |||
pos = list_entry(pos->member.prev, typeof(*pos), member)) | |||
/* | |||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry | |||
* @pos: the type * to use as a loop counter. | |||
* @n: another type * to use as temporary storage | |||
* @head: the head for your list. | |||
* @member: the name of the list_struct within the struct. | |||
*/ | |||
#define list_for_each_entry_safe(pos, n, head, member) \ | |||
for (pos = list_entry((head)->next, typeof(*pos), member), \ | |||
n = list_entry(pos->member.next, typeof(*pos), member); \ | |||
&pos->member != (head); \ | |||
pos = n, n = list_entry(n->member.next, typeof(*n), member)) | |||
/* Return pointer to first true entry, if any, or NULL. A macro | |||
required to allow inlining of cmpfn. */ | |||
#define LIST_FIND(head, cmpfn, type, args...) \ | |||
({ \ | |||
const struct list_head *__i, *__j = NULL; \ | |||
\ | |||
list_for_each(__i, (head)) \ | |||
if (cmpfn((const type)__i , ## args)) { \ | |||
__j = __i; \ | |||
break; \ | |||
} \ | |||
(type)__j; \ | |||
}) | |||
#endif /* _LIST_H_ */ |
@ -0,0 +1,9 @@ | |||
#ifndef STATIC_ALLOC_H_ | |||
#define STATIC_ALLOC_H_ | |||
void * static_alloc(uint32_t size); | |||
uint32_t static_alloc_used(void); | |||
uint32_t next_powerof2(uint32_t value); | |||
#endif /*STATIC_ALLOC_H_*/ |
@ -0,0 +1,240 @@ | |||
#ifndef USB_CDC_H_ | |||
#define USB_CDC_H_ | |||
#include <stdint.h> | |||
/* | |||
* the content of this file comes from | |||
* - linux/include/linux/usb/cdc.h | |||
* with minor modifications: | |||
* - type conversion (e.g. __u8 -> uint8_t) | |||
*/ | |||
/*-------------------------------------------------------------------------*/ | |||
/* | |||
* USB Communications Device Class (CDC) definitions | |||
* | |||
* CDC says how to talk to lots of different types of network adapters, | |||
* notably ethernet adapters and various modems. It's used mostly with | |||
* firmware based USB peripherals. | |||
*/ | |||
#define USB_CDC_SUBCLASS_ACM 0x02 | |||
#define USB_CDC_SUBCLASS_ETHERNET 0x06 | |||
#define USB_CDC_SUBCLASS_WHCM 0x08 | |||
#define USB_CDC_SUBCLASS_DMM 0x09 | |||
#define USB_CDC_SUBCLASS_MDLM 0x0a | |||
#define USB_CDC_SUBCLASS_OBEX 0x0b | |||
#define USB_CDC_PROTO_NONE 0 | |||
#define USB_CDC_ACM_PROTO_AT_V25TER 1 | |||
#define USB_CDC_ACM_PROTO_AT_PCCA101 2 | |||
#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 | |||
#define USB_CDC_ACM_PROTO_AT_GSM 4 | |||
#define USB_CDC_ACM_PROTO_AT_3G 5 | |||
#define USB_CDC_ACM_PROTO_AT_CDMA 6 | |||
#define USB_CDC_ACM_PROTO_VENDOR 0xff | |||
/*-------------------------------------------------------------------------*/ | |||
/* | |||
* Class-Specific descriptors ... there are a couple dozen of them | |||
*/ | |||
#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ | |||
#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ | |||
#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ | |||
#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ | |||
#define USB_CDC_COUNTRY_TYPE 0x07 | |||
#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ | |||
#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ | |||
#define USB_CDC_WHCM_TYPE 0x11 | |||
#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ | |||
#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ | |||
#define USB_CDC_DMM_TYPE 0x14 | |||
#define USB_CDC_OBEX_TYPE 0x15 | |||
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ | |||
struct usb_cdc_header_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint16_t bcdCDC; | |||
} __attribute__ ((packed)); | |||
/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ | |||
struct usb_cdc_call_mgmt_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t bmCapabilities; | |||
#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 | |||
#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 | |||
uint8_t bDataInterface; | |||
} __attribute__ ((packed)); | |||
/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ | |||
struct usb_cdc_acm_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t bmCapabilities; | |||
} __attribute__ ((packed)); | |||
/* capabilities from 5.2.3.3 */ | |||
#define USB_CDC_COMM_FEATURE 0x01 | |||
#define USB_CDC_CAP_LINE 0x02 | |||
#define USB_CDC_CAP_BRK 0x04 | |||
#define USB_CDC_CAP_NOTIFY 0x08 | |||
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ | |||
struct usb_cdc_union_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t bMasterInterface0; | |||
uint8_t bSlaveInterface0; | |||
/* ... and there could be other slave interfaces */ | |||
} __attribute__ ((packed)); | |||
/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */ | |||
struct usb_cdc_country_functional_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t iCountryCodeRelDate; | |||
uint16_t wCountyCode0; | |||
/* ... and there can be a lot of country codes */ | |||
} __attribute__ ((packed)); | |||
/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ | |||
struct usb_cdc_network_terminal_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t bEntityId; | |||
uint8_t iName; | |||
uint8_t bChannelIndex; | |||
uint8_t bPhysicalInterface; | |||
} __attribute__ ((packed)); | |||
/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ | |||
struct usb_cdc_ether_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint8_t iMACAddress; | |||
uint32_t bmEthernetStatistics; | |||
uint16_t wMaxSegmentSize; | |||
uint16_t wNumberMCFilters; | |||
uint8_t bNumberPowerFilters; | |||
} __attribute__ ((packed)); | |||
/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ | |||
struct usb_cdc_mdlm_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
uint16_t bcdVersion; | |||
uint8_t bGUID[16]; | |||
} __attribute__ ((packed)); | |||
/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ | |||
struct usb_cdc_mdlm_detail_desc { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDescriptorSubType; | |||
/* type is associated with mdlm_desc.bGUID */ | |||
uint8_t bGuidDescriptorType; | |||
uint8_t bDetailData[0]; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* | |||
* Class-Specific Control Requests (6.2) | |||
* | |||
* section 3.6.2.1 table 4 has the ACM profile, for modems. | |||
* section 3.8.2 table 10 has the ethernet profile. | |||
* | |||
* Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, | |||
* heavily dependent on the encapsulated (proprietary) command mechanism. | |||
*/ | |||
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 | |||
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 | |||
#define USB_CDC_REQ_SET_LINE_CODING 0x20 | |||
#define USB_CDC_REQ_GET_LINE_CODING 0x21 | |||
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 | |||
#define USB_CDC_REQ_SEND_BREAK 0x23 | |||
#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 | |||
#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 | |||
#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 | |||
#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 | |||
#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 | |||
/* Line Coding Structure from CDC spec 6.2.13 */ | |||
struct usb_cdc_line_coding { | |||
uint32_t dwDTERate; | |||
uint8_t bCharFormat; | |||
#define USB_CDC_1_STOP_BITS 0 | |||
#define USB_CDC_1_5_STOP_BITS 1 | |||
#define USB_CDC_2_STOP_BITS 2 | |||
uint8_t bParityType; | |||
#define USB_CDC_NO_PARITY 0 | |||
#define USB_CDC_ODD_PARITY 1 | |||
#define USB_CDC_EVEN_PARITY 2 | |||
#define USB_CDC_MARK_PARITY 3 | |||
#define USB_CDC_SPACE_PARITY 4 | |||
uint8_t bDataBits; | |||
} __attribute__ ((packed)); | |||
/* table 62; bits in multicast filter */ | |||
#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) | |||
#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ | |||
#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) | |||
#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) | |||
#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ | |||
/*-------------------------------------------------------------------------*/ | |||
/* | |||
* Class-Specific Notifications (6.3) sent by interrupt transfers | |||
* | |||
* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications | |||
* section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS | |||
* RNDIS also defines its own bit-incompatible notifications | |||
*/ | |||
#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 | |||
#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 | |||
#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 | |||
#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a | |||
struct usb_cdc_notification { | |||
uint8_t bmRequestType; | |||
uint8_t bNotificationType; | |||
uint16_t wValue; | |||
uint16_t wIndex; | |||
uint16_t wLength; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
#endif /*USB_CDC_H_*/ |
@ -0,0 +1,553 @@ | |||
#ifndef USB_CH9_H_ | |||
#define USB_CH9_H_ | |||
#include <stdint.h> | |||
/* | |||
* the content of this file comes from | |||
* - linux/include/linux/usb/ch9.h | |||
* with minor modifications: | |||
* - type conversion (e.g. __u8 -> uint8_t) | |||
* - usb_endpoint_descriptor: removed last 2 bytes | |||
*/ | |||
/*-------------------------------------------------------------------------*/ | |||
/* CONTROL REQUEST SUPPORT */ | |||
/* | |||
* USB directions | |||
* | |||
* This bit flag is used in endpoint descriptors' bEndpointAddress field. | |||
* It's also one of three fields in control requests bRequestType. | |||
*/ | |||
#define USB_DIR_OUT 0 /* to device */ | |||
#define USB_DIR_IN 0x80 /* to host */ | |||
/* | |||
* USB types, the second of three bRequestType fields | |||
*/ | |||
#define USB_TYPE_MASK (0x03 << 5) | |||
#define USB_TYPE_STANDARD (0x00 << 5) | |||
#define USB_TYPE_CLASS (0x01 << 5) | |||
#define USB_TYPE_VENDOR (0x02 << 5) | |||
#define USB_TYPE_RESERVED (0x03 << 5) | |||
/* | |||
* USB recipients, the third of three bRequestType fields | |||
*/ | |||
#define USB_RECIP_MASK 0x1f | |||
#define USB_RECIP_DEVICE 0x00 | |||
#define USB_RECIP_INTERFACE 0x01 | |||
#define USB_RECIP_ENDPOINT 0x02 | |||
#define USB_RECIP_OTHER 0x03 | |||
/* From Wireless USB 1.0 */ | |||
#define USB_RECIP_PORT 0x04 | |||
#define USB_RECIP_RPIPE 0x05 | |||
/* | |||
* Standard requests, for the bRequest field of a SETUP packet. | |||
* | |||
* These are qualified by the bRequestType field, so that for example | |||
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved | |||
* by a GET_STATUS request. | |||
*/ | |||
#define USB_REQ_GET_STATUS 0x00 | |||
#define USB_REQ_CLEAR_FEATURE 0x01 | |||
#define USB_REQ_SET_FEATURE 0x03 | |||
#define USB_REQ_SET_ADDRESS 0x05 | |||
#define USB_REQ_GET_DESCRIPTOR 0x06 | |||
#define USB_REQ_SET_DESCRIPTOR 0x07 | |||
#define USB_REQ_GET_CONFIGURATION 0x08 | |||
#define USB_REQ_SET_CONFIGURATION 0x09 | |||
#define USB_REQ_GET_INTERFACE 0x0A | |||
#define USB_REQ_SET_INTERFACE 0x0B | |||
#define USB_REQ_SYNCH_FRAME 0x0C | |||
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ | |||
#define USB_REQ_GET_ENCRYPTION 0x0E | |||
#define USB_REQ_RPIPE_ABORT 0x0E | |||
#define USB_REQ_SET_HANDSHAKE 0x0F | |||
#define USB_REQ_RPIPE_RESET 0x0F | |||
#define USB_REQ_GET_HANDSHAKE 0x10 | |||
#define USB_REQ_SET_CONNECTION 0x11 | |||
#define USB_REQ_SET_SECURITY_DATA 0x12 | |||
#define USB_REQ_GET_SECURITY_DATA 0x13 | |||
#define USB_REQ_SET_WUSB_DATA 0x14 | |||
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 | |||
#define USB_REQ_LOOPBACK_DATA_READ 0x16 | |||
#define USB_REQ_SET_INTERFACE_DS 0x17 | |||
/* | |||
* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and | |||
* are read as a bit array returned by USB_REQ_GET_STATUS. (So there | |||
* are at most sixteen features of each type.) | |||
*/ | |||
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ | |||
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ | |||
#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ | |||
#define USB_DEVICE_BATTERY 2 /* (wireless) */ | |||
#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ | |||
#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ | |||
#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ | |||
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ | |||
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ | |||
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ | |||
/** | |||
* struct usb_ctrlrequest - SETUP data for a USB device control request | |||
* @bRequestType: matches the USB bmRequestType field | |||
* @bRequest: matches the USB bRequest field | |||
* @wValue: matches the USB wValue field (le16 byte order) | |||
* @wIndex: matches the USB wIndex field (le16 byte order) | |||
* @wLength: matches the USB wLength field (le16 byte order) | |||
* | |||
* This structure is used to send control requests to a USB device. It matches | |||
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the | |||
* USB spec for a fuller description of the different fields, and what they are | |||
* used for. | |||
* | |||
* Note that the driver for any interface can issue control requests. | |||
* For most devices, interfaces don't coordinate with each other, so | |||
* such requests may be made at any time. | |||
*/ | |||
struct usb_ctrlrequest { | |||
uint8_t bRequestType; | |||
uint8_t bRequest; | |||
uint16_t wValue; | |||
uint16_t wIndex; | |||
uint16_t wLength; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* | |||
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or | |||
* (rarely) accepted by SET_DESCRIPTOR. | |||
* | |||
* Note that all multi-byte values here are encoded in little endian | |||
* byte order "on the wire". But when exposed through Linux-USB APIs, | |||
* they've been converted to cpu byte order. | |||
*/ | |||
/* | |||
* Descriptor types ... USB 2.0 spec table 9.5 | |||
*/ | |||
#define USB_DT_DEVICE 0x01 | |||
#define USB_DT_CONFIG 0x02 | |||
#define USB_DT_STRING 0x03 | |||
#define USB_DT_INTERFACE 0x04 | |||
#define USB_DT_ENDPOINT 0x05 | |||
#define USB_DT_DEVICE_QUALIFIER 0x06 | |||
#define USB_DT_OTHER_SPEED_CONFIG 0x07 | |||
#define USB_DT_INTERFACE_POWER 0x08 | |||
/* these are from a minor usb 2.0 revision (ECN) */ | |||
#define USB_DT_OTG 0x09 | |||
#define USB_DT_DEBUG 0x0a | |||
#define USB_DT_INTERFACE_ASSOCIATION 0x0b | |||
/* these are from the Wireless USB spec */ | |||
#define USB_DT_SECURITY 0x0c | |||
#define USB_DT_KEY 0x0d | |||
#define USB_DT_ENCRYPTION_TYPE 0x0e | |||
#define USB_DT_BOS 0x0f | |||
#define USB_DT_DEVICE_CAPABILITY 0x10 | |||
#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 | |||
#define USB_DT_WIRE_ADAPTER 0x21 | |||
#define USB_DT_RPIPE 0x22 | |||
/* Conventional codes for class-specific descriptors. The convention is | |||
* defined in the USB "Common Class" Spec (3.11). Individual class specs | |||
* are authoritative for their usage, not the "common class" writeup. | |||
*/ | |||
#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) | |||
#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) | |||
#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) | |||
#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) | |||
#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) | |||
/* All standard descriptors have these 2 fields at the beginning */ | |||
struct usb_descriptor_header { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_DEVICE: Device descriptor */ | |||
struct usb_device_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t bcdUSB; | |||
uint8_t bDeviceClass; | |||
uint8_t bDeviceSubClass; | |||
uint8_t bDeviceProtocol; | |||
uint8_t bMaxPacketSize0; | |||
uint16_t idVendor; | |||
uint16_t idProduct; | |||
uint16_t bcdDevice; | |||
uint8_t iManufacturer; | |||
uint8_t iProduct; | |||
uint8_t iSerialNumber; | |||
uint8_t bNumConfigurations; | |||
} __attribute__ ((packed)); | |||
#define USB_DT_DEVICE_SIZE 18 | |||
/* | |||
* Device and/or Interface Class codes | |||
* as found in bDeviceClass or bInterfaceClass | |||
* and defined by www.usb.org documents | |||
*/ | |||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ | |||
#define USB_CLASS_AUDIO 1 | |||
#define USB_CLASS_COMM 2 | |||
#define USB_CLASS_HID 3 | |||
#define USB_CLASS_PHYSICAL 5 | |||
#define USB_CLASS_STILL_IMAGE 6 | |||
#define USB_CLASS_PRINTER 7 | |||
#define USB_CLASS_MASS_STORAGE 8 | |||
#define USB_CLASS_HUB 9 | |||
#define USB_CLASS_CDC_DATA 0x0a | |||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ | |||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ | |||
#define USB_CLASS_VIDEO 0x0e | |||
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 | |||
#define USB_CLASS_MISC 0xef | |||
#define USB_CLASS_APP_SPEC 0xfe | |||
#define USB_CLASS_VENDOR_SPEC 0xff | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_CONFIG: Configuration descriptor information. | |||
* | |||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the | |||
* descriptor type is different. Highspeed-capable devices can look | |||
* different depending on what speed they're currently running. Only | |||
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG | |||
* descriptors. | |||
*/ | |||
struct usb_config_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t wTotalLength; | |||
uint8_t bNumInterfaces; | |||
uint8_t bConfigurationValue; | |||
uint8_t iConfiguration; | |||
uint8_t bmAttributes; | |||
uint8_t bMaxPower; | |||
} __attribute__ ((packed)); | |||
#define USB_DT_CONFIG_SIZE 9 | |||
/* from config descriptor bmAttributes */ | |||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ | |||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ | |||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ | |||
#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_STRING: String descriptor */ | |||
struct usb_string_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t wData[1]; /* UTF-16LE encoded */ | |||
} __attribute__ ((packed)); | |||
/* note that "string" zero is special, it holds language codes that | |||
* the device supports, not Unicode characters. | |||
*/ | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_INTERFACE: Interface descriptor */ | |||
struct usb_interface_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bInterfaceNumber; | |||
uint8_t bAlternateSetting; | |||
uint8_t bNumEndpoints; | |||
uint8_t bInterfaceClass; | |||
uint8_t bInterfaceSubClass; | |||
uint8_t bInterfaceProtocol; | |||
uint8_t iInterface; | |||
} __attribute__ ((packed)); | |||
#define USB_DT_INTERFACE_SIZE 9 | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_ENDPOINT: Endpoint descriptor */ | |||
struct usb_endpoint_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bEndpointAddress; | |||
uint8_t bmAttributes; | |||
uint16_t wMaxPacketSize; | |||
uint8_t bInterval; | |||
/* NOTE: these two are _only_ in audio endpoints. */ | |||
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ | |||
// uint8_t bRefresh; | |||
// uint8_t bSynchAddress; | |||
} __attribute__ ((packed)); | |||
#define USB_DT_ENDPOINT_SIZE 7 | |||
//#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ | |||
/* | |||
* Endpoints | |||
*/ | |||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ | |||
#define USB_ENDPOINT_DIR_MASK 0x80 | |||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ | |||
#define USB_ENDPOINT_XFER_CONTROL 0 | |||
#define USB_ENDPOINT_XFER_ISOC 1 | |||
#define USB_ENDPOINT_XFER_BULK 2 | |||
#define USB_ENDPOINT_XFER_INT 3 | |||
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ | |||
struct usb_qualifier_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t bcdUSB; | |||
uint8_t bDeviceClass; | |||
uint8_t bDeviceSubClass; | |||
uint8_t bDeviceProtocol; | |||
uint8_t bMaxPacketSize0; | |||
uint8_t bNumConfigurations; | |||
uint8_t bRESERVED; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_OTG (from OTG 1.0a supplement) */ | |||
struct usb_otg_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bmAttributes; /* support for HNP, SRP, etc */ | |||
} __attribute__ ((packed)); | |||
/* from usb_otg_descriptor.bmAttributes */ | |||
#define USB_OTG_SRP (1 << 0) | |||
#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ | |||
struct usb_debug_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
/* bulk endpoints with 8 byte maxpacket */ | |||
uint8_t bDebugInEndpoint; | |||
uint8_t bDebugOutEndpoint; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */ | |||
struct usb_interface_assoc_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bFirstInterface; | |||
uint8_t bInterfaceCount; | |||
uint8_t bFunctionClass; | |||
uint8_t bFunctionSubClass; | |||
uint8_t bFunctionProtocol; | |||
uint8_t iFunction; | |||
} __attribute__ ((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_SECURITY: group of wireless security descriptors, including | |||
* encryption types available for setting up a CC/association. | |||
*/ | |||
struct usb_security_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t wTotalLength; | |||
uint8_t bNumEncryptionTypes; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys | |||
* may be retrieved. | |||
*/ | |||
struct usb_key_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t tTKID[3]; | |||
uint8_t bReserved; | |||
uint8_t bKeyData[0]; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ | |||
struct usb_encryption_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bEncryptionType; | |||
#define USB_ENC_TYPE_UNSECURE 0 | |||
#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ | |||
#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ | |||
#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ | |||
uint8_t bEncryptionValue; /* use in SET_ENCRYPTION */ | |||
uint8_t bAuthKeyIndex; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_BOS: group of wireless capabilities */ | |||
struct usb_bos_descriptor { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint16_t wTotalLength; | |||
uint8_t bNumDeviceCaps; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ | |||
struct usb_dev_cap_header { | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDevCapabilityType; | |||
} __attribute__((packed)); | |||
#define USB_CAP_TYPE_WIRELESS_USB 1 | |||
struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ | |||
uint8_t bLength; | |||
uint8_t bDescriptorType; | |||
uint8_t bDevCapabilityType; | |||
uint8_t bmAttributes; | |||
#define USB_WIRELESS_P2P_DRD (1 << 1) | |||
#define USB_WIRELESS_BEACON_MASK (3 << 2) | |||
#define USB_WIRELESS_BEACON_SELF (1 << 2) | |||
#define USB_WIRELESS_BEACON_DIRECTED (2 << 2) | |||
#define USB_WIRELESS_BEACON_NONE (3 << 2) | |||
uint16_t wPHYRates; /* bit rates, Mbps */ | |||
#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ | |||
#define USB_WIRELESS_PHY_80 (1 << 1) | |||
#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ | |||
#define USB_WIRELESS_PHY_160 (1 << 3) | |||
#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ | |||
#define USB_WIRELESS_PHY_320 (1 << 5) | |||
#define USB_WIRELESS_PHY_400 (1 << 6) | |||
#define USB_WIRELESS_PHY_480 (1 << 7) | |||
uint8_t bmTFITXPowerInfo; /* TFI power levels */ | |||
uint8_t bmFFITXPowerInfo; /* FFI power levels */ | |||
uint16_t bmBandGroup; | |||
uint8_t bReserved; | |||
} __attribute__((packed)); | |||
/*-------------------------------------------------------------------------*/ | |||
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with | |||
* each endpoint descriptor for a wireless device | |||
*/ | |||
struct usb_wireless_ep_comp_descriptor { | |||
uint8_t bLength; | |||