aboutsummaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/arm_atsam.mk56
-rw-r--r--tmk_core/common.mk6
-rw-r--r--tmk_core/common/arm_atsam/bootloader.c19
-rw-r--r--tmk_core/common/arm_atsam/eeprom.c98
-rw-r--r--tmk_core/common/arm_atsam/printf.h8
-rw-r--r--tmk_core/common/arm_atsam/suspend.c17
-rw-r--r--tmk_core/common/arm_atsam/timer.c59
-rw-r--r--tmk_core/common/print.h30
-rw-r--r--tmk_core/common/report.h5
-rw-r--r--tmk_core/protocol/arm_atsam.mk26
-rw-r--r--tmk_core/protocol/arm_atsam/adc.c99
-rw-r--r--tmk_core/protocol/arm_atsam/adc.h37
-rw-r--r--tmk_core/protocol/arm_atsam/arm_atsam_protocol.h45
-rw-r--r--tmk_core/protocol/arm_atsam/clks.c439
-rw-r--r--tmk_core/protocol/arm_atsam/clks.h90
-rw-r--r--tmk_core/protocol/arm_atsam/d51_util.c165
-rw-r--r--tmk_core/protocol/arm_atsam/d51_util.h185
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.c585
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.h108
-rw-r--r--tmk_core/protocol/arm_atsam/issi3733_driver.h201
-rw-r--r--tmk_core/protocol/arm_atsam/led_matrix.c509
-rw-r--r--tmk_core/protocol/arm_atsam/led_matrix.h142
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.c279
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.h23
-rw-r--r--tmk_core/protocol/arm_atsam/md_bootloader.h18
-rw-r--r--tmk_core/protocol/arm_atsam/spi.c90
-rw-r--r--tmk_core/protocol/arm_atsam/spi.h63
-rw-r--r--tmk_core/protocol/arm_atsam/startup.c548
-rw-r--r--tmk_core/protocol/arm_atsam/usb/compiler.h1177
-rw-r--r--tmk_core/protocol/arm_atsam/usb/conf_usb.h163
-rw-r--r--tmk_core/protocol/arm_atsam/usb/main_usb.c118
-rw-r--r--tmk_core/protocol/arm_atsam/usb/spfssf.c268
-rw-r--r--tmk_core/protocol/arm_atsam/usb/spfssf.h57
-rw-r--r--tmk_core/protocol/arm_atsam/usb/status_codes.h158
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udc.c1164
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udc.h260
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udc_desc.h135
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udd.h396
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi.h133
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_cdc.c1384
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_cdc.h381
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h72
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_device_conf.h715
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h32
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid.c162
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid.h85
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c845
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h109
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h60
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c179
-rw-r--r--tmk_core/protocol/arm_atsam/usb/ui.c106
-rw-r--r--tmk_core/protocol/arm_atsam/usb/ui.h82
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb.c1144
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb.h492
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb2422.c412
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb2422.h405
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_atmel.h190
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_device_udd.c1097
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_main.h97
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_protocol.h498
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h193
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h319
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_util.c59
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_util.h10
-rw-r--r--tmk_core/protocol/arm_atsam/wait_api.h8
65 files changed, 17114 insertions, 1 deletions
diff --git a/tmk_core/arm_atsam.mk b/tmk_core/arm_atsam.mk
new file mode 100644
index 000000000..ef412d59d
--- /dev/null
+++ b/tmk_core/arm_atsam.mk
@@ -0,0 +1,56 @@
1# Hey Emacs, this is a -*- makefile -*-
2##############################################################################
3# Compiler settings
4#
5CC = arm-none-eabi-gcc
6OBJCOPY = arm-none-eabi-objcopy
7OBJDUMP = arm-none-eabi-objdump
8SIZE = arm-none-eabi-size
9AR = arm-none-eabi-ar rcs
10NM = arm-none-eabi-nm
11HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
12EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
13BIN =
14
15COMMON_VPATH += $(LIB_PATH)/arm_atsam/packs/atmel/SAMD51_DFP/1.0.70/include
16COMMON_VPATH += $(LIB_PATH)/arm_atsam/packs/arm/cmsis/5.0.1/CMSIS/Include
17
18COMPILEFLAGS += -funsigned-char
19COMPILEFLAGS += -funsigned-bitfields
20COMPILEFLAGS += -ffunction-sections
21COMPILEFLAGS += -fshort-enums
22COMPILEFLAGS += -fno-inline-small-functions
23COMPILEFLAGS += -fno-strict-aliasing
24COMPILEFLAGS += -mfloat-abi=hard
25COMPILEFLAGS += -mfpu=fpv4-sp-d16
26COMPILEFLAGS += -mthumb
27
28#ALLOW_WARNINGS = yes
29
30CFLAGS += $(COMPILEFLAGS)
31
32CPPFLAGS += $(COMPILEFLAGS)
33CPPFLAGS += -fno-exceptions -std=c++11
34
35LDFLAGS +=-Wl,--gc-sections
36LDFLAGS += -Wl,-Map="%OUT%%PROJ_NAME%.map"
37LDFLAGS += -Wl,--start-group
38LDFLAGS += -Wl,--end-group
39LDFLAGS += -Wl,--gc-sections
40LDFLAGS += -T$(LIB_PATH)/arm_atsam/packs/atmel/SAMD51_DFP/1.0.70/gcc/gcc/samd51j18a_flash.ld
41
42OPT_DEFS += -DPROTOCOL_ARM_ATSAM
43
44MCUFLAGS = -mcpu=$(MCU)
45MCUFLAGS += -D__$(ARM_ATSAM)__
46
47# List any extra directories to look for libraries here.
48# Each directory must be seperated by a space.
49# Use forward slashes for directory separators.
50# For a directory that has spaces, enclose it in quotes.
51EXTRALIBDIRS =
52
53# Convert hex to bin.
54bin: $(BUILD_DIR)/$(TARGET).hex
55 $(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
56 $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin;
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index 3e407f157..fd91d29dc 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -3,6 +3,8 @@ ifeq ($(PLATFORM),AVR)
3 PLATFORM_COMMON_DIR = $(COMMON_DIR)/avr 3 PLATFORM_COMMON_DIR = $(COMMON_DIR)/avr
4else ifeq ($(PLATFORM),CHIBIOS) 4else ifeq ($(PLATFORM),CHIBIOS)
5 PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios 5 PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios
6else ifeq ($(PLATFORM),ARM_ATSAM)
7 PLATFORM_COMMON_DIR = $(COMMON_DIR)/arm_atsam
6else 8else
7 PLATFORM_COMMON_DIR = $(COMMON_DIR)/test 9 PLATFORM_COMMON_DIR = $(COMMON_DIR)/test
8endif 10endif
@@ -35,6 +37,10 @@ ifeq ($(PLATFORM),CHIBIOS)
35 endif 37 endif
36endif 38endif
37 39
40ifeq ($(PLATFORM),ARM_ATSAM)
41 TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
42endif
43
38ifeq ($(PLATFORM),TEST) 44ifeq ($(PLATFORM),TEST)
39 TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c 45 TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
40endif 46endif
diff --git a/tmk_core/common/arm_atsam/bootloader.c b/tmk_core/common/arm_atsam/bootloader.c
new file mode 100644
index 000000000..5155d9ff0
--- /dev/null
+++ b/tmk_core/common/arm_atsam/bootloader.c
@@ -0,0 +1,19 @@
1/* Copyright 2017 Fred Sundvik
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "bootloader.h"
18
19void bootloader_jump(void) {}
diff --git a/tmk_core/common/arm_atsam/eeprom.c b/tmk_core/common/arm_atsam/eeprom.c
new file mode 100644
index 000000000..61cc039ef
--- /dev/null
+++ b/tmk_core/common/arm_atsam/eeprom.c
@@ -0,0 +1,98 @@
1/* Copyright 2017 Fred Sundvik
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "eeprom.h"
18
19#define EEPROM_SIZE 32
20
21static uint8_t buffer[EEPROM_SIZE];
22
23uint8_t eeprom_read_byte(const uint8_t *addr) {
24 uintptr_t offset = (uintptr_t)addr;
25 return buffer[offset];
26}
27
28void eeprom_write_byte(uint8_t *addr, uint8_t value) {
29 uintptr_t offset = (uintptr_t)addr;
30 buffer[offset] = value;
31}
32
33uint16_t eeprom_read_word(const uint16_t *addr) {
34 const uint8_t *p = (const uint8_t *)addr;
35 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
36}
37
38uint32_t eeprom_read_dword(const uint32_t *addr) {
39 const uint8_t *p = (const uint8_t *)addr;
40 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
41 | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
42}
43
44void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
45 const uint8_t *p = (const uint8_t *)addr;
46 uint8_t *dest = (uint8_t *)buf;
47 while (len--) {
48 *dest++ = eeprom_read_byte(p++);
49 }
50}
51
52void eeprom_write_word(uint16_t *addr, uint16_t value) {
53 uint8_t *p = (uint8_t *)addr;
54 eeprom_write_byte(p++, value);
55 eeprom_write_byte(p, value >> 8);
56}
57
58void eeprom_write_dword(uint32_t *addr, uint32_t value) {
59 uint8_t *p = (uint8_t *)addr;
60 eeprom_write_byte(p++, value);
61 eeprom_write_byte(p++, value >> 8);
62 eeprom_write_byte(p++, value >> 16);
63 eeprom_write_byte(p, value >> 24);
64}
65
66void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
67 uint8_t *p = (uint8_t *)addr;
68 const uint8_t *src = (const uint8_t *)buf;
69 while (len--) {
70 eeprom_write_byte(p++, *src++);
71 }
72}
73
74void eeprom_update_byte(uint8_t *addr, uint8_t value) {
75 eeprom_write_byte(addr, value);
76}
77
78void eeprom_update_word(uint16_t *addr, uint16_t value) {
79 uint8_t *p = (uint8_t *)addr;
80 eeprom_write_byte(p++, value);
81 eeprom_write_byte(p, value >> 8);
82}
83
84void eeprom_update_dword(uint32_t *addr, uint32_t value) {
85 uint8_t *p = (uint8_t *)addr;
86 eeprom_write_byte(p++, value);
87 eeprom_write_byte(p++, value >> 8);
88 eeprom_write_byte(p++, value >> 16);
89 eeprom_write_byte(p, value >> 24);
90}
91
92void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
93 uint8_t *p = (uint8_t *)addr;
94 const uint8_t *src = (const uint8_t *)buf;
95 while (len--) {
96 eeprom_write_byte(p++, *src++);
97 }
98}
diff --git a/tmk_core/common/arm_atsam/printf.h b/tmk_core/common/arm_atsam/printf.h
new file mode 100644
index 000000000..582c83bf5
--- /dev/null
+++ b/tmk_core/common/arm_atsam/printf.h
@@ -0,0 +1,8 @@
1#ifndef _PRINTF_H_
2#define _PRINTF_H_
3
4#define __xprintf dpf
5int dpf(const char *_Format, ...);
6
7#endif //_PRINTF_H_
8
diff --git a/tmk_core/common/arm_atsam/suspend.c b/tmk_core/common/arm_atsam/suspend.c
new file mode 100644
index 000000000..01d1930ea
--- /dev/null
+++ b/tmk_core/common/arm_atsam/suspend.c
@@ -0,0 +1,17 @@
1/* Copyright 2017 Fred Sundvik
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
diff --git a/tmk_core/common/arm_atsam/timer.c b/tmk_core/common/arm_atsam/timer.c
new file mode 100644
index 000000000..bcfe5002c
--- /dev/null
+++ b/tmk_core/common/arm_atsam/timer.c
@@ -0,0 +1,59 @@
1#include "samd51j18a.h"
2#include "timer.h"
3#include "tmk_core/protocol/arm_atsam/clks.h"
4
5void set_time(uint64_t tset)
6{
7 ms_clk = tset;
8}
9
10void timer_init(void)
11{
12 ms_clk = 0;
13}
14
15uint16_t timer_read(void)
16{
17 return (uint16_t)ms_clk;
18}
19
20uint32_t timer_read32(void)
21{
22 return (uint32_t)ms_clk;
23}
24
25uint64_t timer_read64(void)
26{
27 return ms_clk;
28}
29
30uint16_t timer_elapsed(uint16_t tlast)
31{
32 return TIMER_DIFF_16(timer_read(), tlast);
33}
34
35uint32_t timer_elapsed32(uint32_t tlast)
36{
37 return TIMER_DIFF_32(timer_read32(), tlast);
38}
39
40uint32_t timer_elapsed64(uint32_t tlast)
41{
42 uint64_t tnow = timer_read64();
43 return (tnow >= tlast ? tnow - tlast : UINT64_MAX - tlast + tnow);
44}
45
46void timer_clear(void)
47{
48 ms_clk = 0;
49}
50
51void wait_ms(uint64_t msec)
52{
53 CLK_delay_ms(msec);
54}
55
56void wait_us(uint16_t usec)
57{
58 CLK_delay_us(usec);
59}
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
index 8836c0fc7..9cbe67bad 100644
--- a/tmk_core/common/print.h
+++ b/tmk_core/common/print.h
@@ -99,6 +99,34 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
99 99
100# endif /* USER_PRINT / NORMAL PRINT */ 100# endif /* USER_PRINT / NORMAL PRINT */
101 101
102#elif defined(PROTOCOL_ARM_ATSAM) /* PROTOCOL_ARM_ATSAM */
103
104# include "arm_atsam/printf.h"
105
106# ifdef USER_PRINT /* USER_PRINT */
107
108// Remove normal print defines
109# define print(s)
110# define println(s)
111# define xprintf(fmt, ...)
112
113// Create user print defines
114# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
115# define uprint(s) xprintf(s)
116# define uprintln(s) xprintf(s "\r\n")
117
118# else /* NORMAL PRINT */
119
120// Create user & normal print defines
121# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
122# define print(s) xprintf(s)
123# define println(s) xprintf(s "\r\n")
124# define uprint(s) print(s)
125# define uprintln(s) println(s)
126# define uprintf(fmt, ...) xprintf(fmt, ...)
127
128# endif /* USER_PRINT / NORMAL PRINT */
129
102#elif defined(__arm__) /* __arm__ */ 130#elif defined(__arm__) /* __arm__ */
103 131
104# include "mbed/xprintf.h" 132# include "mbed/xprintf.h"
@@ -130,7 +158,7 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
130/* TODO: to select output destinations: UART/USBSerial */ 158/* TODO: to select output destinations: UART/USBSerial */
131# define print_set_sendchar(func) 159# define print_set_sendchar(func)
132 160
133#endif /* __AVR__ / PROTOCOL_CHIBIOS / __arm__ */ 161#endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM / __arm__ */
134 162
135// User print disables the normal print messages in the body of QMK/TMK code and 163// User print disables the normal print messages in the body of QMK/TMK code and
136// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do 164// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index 6c27eb9dc..167f38275 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -84,6 +84,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
84 #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE 84 #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
85 #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2) 85 #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
86 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) 86 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87 #elif defined(PROTOCOL_ARM_ATSAM)
88 #include "protocol/arm_atsam/usb/udi_device_epsize.h"
89 #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
90 #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
91 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87 #else 92 #else
88 #error "NKRO not supported with this protocol" 93 #error "NKRO not supported with this protocol"
89#endif 94#endif
diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk
new file mode 100644
index 000000000..d535b64cd
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam.mk
@@ -0,0 +1,26 @@
1ARM_ATSAM_DIR = protocol/arm_atsam
2
3SRC += $(ARM_ATSAM_DIR)/adc.c
4SRC += $(ARM_ATSAM_DIR)/clks.c
5SRC += $(ARM_ATSAM_DIR)/d51_util.c
6SRC += $(ARM_ATSAM_DIR)/i2c_master.c
7SRC += $(ARM_ATSAM_DIR)/led_matrix.c
8SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
9SRC += $(ARM_ATSAM_DIR)/spi.c
10SRC += $(ARM_ATSAM_DIR)/startup.c
11
12SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c
13SRC += $(ARM_ATSAM_DIR)/usb/spfssf.c
14SRC += $(ARM_ATSAM_DIR)/usb/udc.c
15SRC += $(ARM_ATSAM_DIR)/usb/udi_cdc.c
16SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
17SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
18SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
19SRC += $(ARM_ATSAM_DIR)/usb/ui.c
20SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
21SRC += $(ARM_ATSAM_DIR)/usb/usb.c
22SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
23SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c
24
25# Search Path
26VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR)
diff --git a/tmk_core/protocol/arm_atsam/adc.c b/tmk_core/protocol/arm_atsam/adc.c
new file mode 100644
index 000000000..ab77f9240
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/adc.c
@@ -0,0 +1,99 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20uint16_t v_5v;
21uint16_t v_5v_avg;
22uint16_t v_con_1;
23uint16_t v_con_2;
24uint16_t v_con_1_boot;
25uint16_t v_con_2_boot;
26
27void ADC0_clock_init(void)
28{
29 DBGC(DC_ADC0_CLOCK_INIT_BEGIN);
30
31 MCLK->APBDMASK.bit.ADC0_ = 1; //ADC0 Clock Enable
32
33 GCLK->PCHCTRL[ADC0_GCLK_ID].bit.GEN = GEN_OSC0; //Select generator clock
34 GCLK->PCHCTRL[ADC0_GCLK_ID].bit.CHEN = 1; //Enable peripheral clock
35
36 DBGC(DC_ADC0_CLOCK_INIT_COMPLETE);
37}
38
39void ADC0_init(void)
40{
41 DBGC(DC_ADC0_INIT_BEGIN);
42
43 //MCU
44 PORT->Group[1].DIRCLR.reg = 1 << 0; //PB00 as input 5V
45 PORT->Group[1].DIRCLR.reg = 1 << 1; //PB01 as input CON2
46 PORT->Group[1].DIRCLR.reg = 1 << 2; //PB02 as input CON1
47 PORT->Group[1].PMUX[0].bit.PMUXE = 1; //PB00 mux select B ADC 5V
48 PORT->Group[1].PMUX[0].bit.PMUXO = 1; //PB01 mux select B ADC CON2
49 PORT->Group[1].PMUX[1].bit.PMUXE = 1; //PB02 mux select B ADC CON1
50 PORT->Group[1].PINCFG[0].bit.PMUXEN = 1; //PB01 mux ADC Enable 5V
51 PORT->Group[1].PINCFG[1].bit.PMUXEN = 1; //PB01 mux ADC Enable CON2
52 PORT->Group[1].PINCFG[2].bit.PMUXEN = 1; //PB02 mux ADC Enable CON1
53
54 //ADC
55 ADC0->CTRLA.bit.SWRST = 1;
56 while (ADC0->SYNCBUSY.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_1); }
57 while (ADC0->CTRLA.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_2); }
58
59 //Clock divide
60 ADC0->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV2_Val;
61
62 //Averaging
63 ADC0->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_4_Val;
64 while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_1); }
65 if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_1_Val) ADC0->AVGCTRL.bit.ADJRES = 0;
66 else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_2_Val) ADC0->AVGCTRL.bit.ADJRES = 1;
67 else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_4_Val) ADC0->AVGCTRL.bit.ADJRES = 2;
68 else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_8_Val) ADC0->AVGCTRL.bit.ADJRES = 3;
69 else ADC0->AVGCTRL.bit.ADJRES = 4;
70 while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_2); }
71
72 //Settling
73 ADC0->SAMPCTRL.bit.SAMPLEN = 45; //Sampling Time Length: 1-63, 1 ADC CLK per
74 while (ADC0->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC0_SAMPCTRL_SYNCING_1); }
75
76 //Load factory calibration data
77 ADC0->CALIB.bit.BIASCOMP = (ADC0_FUSES_BIASCOMP_ADDR >> ADC0_FUSES_BIASCOMP_Pos) & ADC0_FUSES_BIASCOMP_Msk;
78 ADC0->CALIB.bit.BIASR2R = (ADC0_FUSES_BIASR2R_ADDR >> ADC0_FUSES_BIASR2R_Pos) & ADC0_FUSES_BIASR2R_Msk;
79 ADC0->CALIB.bit.BIASREFBUF = (ADC0_FUSES_BIASREFBUF_ADDR >> ADC0_FUSES_BIASREFBUF_Pos) & ADC0_FUSES_BIASREFBUF_Msk;
80
81 //Enable
82 ADC0->CTRLA.bit.ENABLE = 1;
83 while (ADC0->SYNCBUSY.bit.ENABLE) { DBGC(DC_ADC0_ENABLE_SYNCING_1); }
84
85 DBGC(DC_ADC0_INIT_COMPLETE);
86}
87
88uint16_t adc_get(uint8_t muxpos)
89{
90 ADC0->INPUTCTRL.bit.MUXPOS = muxpos;
91 while (ADC0->SYNCBUSY.bit.INPUTCTRL) {}
92
93 ADC0->SWTRIG.bit.START = 1;
94 while (ADC0->SYNCBUSY.bit.SWTRIG) {}
95 while (!ADC0->INTFLAG.bit.RESRDY) {}
96
97 return ADC0->RESULT.reg;
98}
99
diff --git a/tmk_core/protocol/arm_atsam/adc.h b/tmk_core/protocol/arm_atsam/adc.h
new file mode 100644
index 000000000..5a90ece3f
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/adc.h
@@ -0,0 +1,37 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _ADC_H_
19#define _ADC_H_
20
21#define ADC_5V_START_LEVEL 2365
22
23#define ADC_5V ADC_INPUTCTRL_MUXPOS_AIN12_Val
24#define ADC_CON1 ADC_INPUTCTRL_MUXPOS_AIN14_Val
25#define ADC_CON2 ADC_INPUTCTRL_MUXPOS_AIN13_Val
26
27extern uint16_t v_5v;
28extern uint16_t v_5v_avg;
29extern uint16_t v_con_1;
30extern uint16_t v_con_2;
31extern uint16_t v_con_1_boot;
32extern uint16_t v_con_2_boot;
33
34void ADC0_clock_init(void);
35void ADC0_init(void);
36
37#endif //_ADC_H_
diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
new file mode 100644
index 000000000..be73beccd
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
@@ -0,0 +1,45 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _ARM_ATSAM_PROTOCOL_H_
19#define _ARM_ATSAM_PROTOCOL_H_
20
21#include "samd51j18a.h"
22#include "md_bootloader.h"
23
24#include "d51_util.h"
25#include "clks.h"
26#include "adc.h"
27#include "i2c_master.h"
28#include "spi.h"
29
30#include "./usb/usb2422.h"
31
32#ifndef MD_BOOTLOADER
33
34#include "main_arm_atsam.h"
35#include "led_matrix.h"
36#include "issi3733_driver.h"
37#include "./usb/compiler.h"
38#include "./usb/udc.h"
39#include "./usb/spfssf.h"
40#include "./usb/udi_cdc.h"
41
42#endif //MD_BOOTLOADER
43
44#endif //_ARM_ATSAM_PROTOCOL_H_
45
diff --git a/tmk_core/protocol/arm_atsam/clks.c b/tmk_core/protocol/arm_atsam/clks.c
new file mode 100644
index 000000000..8768d0a99
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/clks.c
@@ -0,0 +1,439 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20#include <string.h>
21
22volatile clk_t system_clks;
23volatile uint64_t ms_clk;
24
25volatile uint8_t us_delay_done;
26
27const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5};
28const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35};
29
30#define USE_DPLL_IND 0
31#define USE_DPLL_DEF GCLK_SOURCE_DPLL0
32
33void CLK_oscctrl_init(void)
34{
35 Oscctrl *posctrl = OSCCTRL;
36 Gclk *pgclk = GCLK;
37
38 DBGC(DC_CLK_OSC_INIT_BEGIN);
39
40 //default setup on por
41 system_clks.freq_dfll = FREQ_DFLL_DEFAULT;
42 system_clks.freq_gclk[0] = system_clks.freq_dfll;
43
44 //configure and startup 16MHz xosc0
45 posctrl->XOSCCTRL[0].bit.ENABLE = 0;
46 posctrl->XOSCCTRL[0].bit.STARTUP = 0xD;
47 posctrl->XOSCCTRL[0].bit.ENALC = 1;
48 posctrl->XOSCCTRL[0].bit.IMULT = 5;
49 posctrl->XOSCCTRL[0].bit.IPTAT = 3;
50 posctrl->XOSCCTRL[0].bit.ONDEMAND = 0;
51 posctrl->XOSCCTRL[0].bit.XTALEN = 1;
52 posctrl->XOSCCTRL[0].bit.ENABLE = 1;
53 while (posctrl->STATUS.bit.XOSCRDY0 == 0) { DBGC(DC_CLK_OSC_INIT_XOSC0_SYNC); }
54 system_clks.freq_xosc0 = FREQ_XOSC0;
55
56 //configure and startup DPLL
57 posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 0;
58 while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE); }
59 posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.REFCLK = 2; //select XOSC0 (16MHz)
60 posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV = 7; //16 MHz / (2 * (7 + 1)) = 1 MHz
61 posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR = PLL_RATIO; //1 MHz * (PLL_RATIO(47) + 1) = 48MHz
62 while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.DPLLRATIO) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_RATIO); }
63 posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ONDEMAND = 0;
64 posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 1;
65 while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE); }
66 while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.LOCK == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_LOCK); }
67 while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.CLKRDY == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY); }
68 system_clks.freq_dpll[0] = (system_clks.freq_xosc0 / 2 / (posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV + 1)) * (posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR + 1);
69
70 //change gclk0 to DPLL
71 pgclk->GENCTRL[GEN_DPLL0].bit.SRC = USE_DPLL_DEF;
72 while (pgclk->SYNCBUSY.bit.GENCTRL0) { DBGC(DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0); }
73
74 system_clks.freq_gclk[0] = system_clks.freq_dpll[0];
75
76 DBGC(DC_CLK_OSC_INIT_COMPLETE);
77}
78
79//configure for 1MHz (1 usec timebase)
80//call CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
81uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq)
82{
83 Gclk *pgclk = GCLK;
84
85 DBGC(DC_CLK_SET_GCLK_FREQ_BEGIN);
86
87 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_1); }
88 pgclk->GENCTRL[gclkn].bit.SRC = USE_DPLL_DEF;
89 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_2); }
90 pgclk->GENCTRL[gclkn].bit.DIV = (uint8_t)(system_clks.freq_dpll[0] / freq);
91 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_3); }
92 pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
93 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_4); }
94 pgclk->GENCTRL[gclkn].bit.GENEN = 1;
95 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_5); }
96 system_clks.freq_gclk[gclkn] = system_clks.freq_dpll[0] / pgclk->GENCTRL[gclkn].bit.DIV;
97
98 DBGC(DC_CLK_SET_GCLK_FREQ_COMPLETE);
99
100 return system_clks.freq_gclk[gclkn];
101}
102
103void CLK_init_osc(void)
104{
105 uint8_t gclkn = GEN_OSC0;
106 Gclk *pgclk = GCLK;
107
108 DBGC(DC_CLK_INIT_OSC_BEGIN);
109
110 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_1); }
111 pgclk->GENCTRL[gclkn].bit.SRC = GCLK_SOURCE_XOSC0;
112 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_2); }
113 pgclk->GENCTRL[gclkn].bit.DIV = 1;
114 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_3); }
115 pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
116 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_4); }
117 pgclk->GENCTRL[gclkn].bit.GENEN = 1;
118 while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_5); }
119 system_clks.freq_gclk[gclkn] = system_clks.freq_xosc0;
120
121 DBGC(DC_CLK_INIT_OSC_COMPLETE);
122}
123
124void CLK_reset_time(void)
125{
126 Tc *ptc4 = TC4;
127 Tc *ptc0 = TC0;
128
129 ms_clk = 0;
130
131 DBGC(DC_CLK_RESET_TIME_BEGIN);
132
133 //stop counters
134 ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
135 while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
136 ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
137 while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
138 //zero counters
139 ptc4->COUNT16.COUNT.reg = 0;
140 while (ptc4->COUNT16.SYNCBUSY.bit.COUNT) {}
141 ptc0->COUNT32.COUNT.reg = 0;
142 while (ptc0->COUNT32.SYNCBUSY.bit.COUNT) {}
143 //start counters
144 ptc0->COUNT32.CTRLA.bit.ENABLE = 1;
145 while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
146 ptc4->COUNT16.CTRLA.bit.ENABLE = 1;
147 while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
148
149 DBGC(DC_CLK_RESET_TIME_COMPLETE);
150}
151
152void TC4_Handler()
153{
154 if (TC4->COUNT16.INTFLAG.bit.MC0)
155 {
156 TC4->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
157 ms_clk++;
158 }
159}
160
161void TC5_Handler()
162{
163 if (TC5->COUNT16.INTFLAG.bit.MC0)
164 {
165 TC5->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
166 us_delay_done = 1;
167 TC5->COUNT16.CTRLA.bit.ENABLE = 0;
168 while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
169 }
170}
171
172uint32_t CLK_enable_timebase(void)
173{
174 Gclk *pgclk = GCLK;
175 Mclk *pmclk = MCLK;
176 Tc *ptc4 = TC4;
177 Tc *ptc5 = TC5;
178 Tc *ptc0 = TC0;
179 Evsys *pevsys = EVSYS;
180
181 DBGC(DC_CLK_ENABLE_TIMEBASE_BEGIN);
182
183 //gclk2 highspeed time base
184 CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
185 CLK_init_osc();
186
187 //unmask TC4, sourcegclk2 to TC4
188 pmclk->APBCMASK.bit.TC4_ = 1;
189 pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45;
190 pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1;
191
192 //unmask TC5 sourcegclk2 to TC5
193 pmclk->APBCMASK.bit.TC5_ = 1;
194 pgclk->PCHCTRL[TC5_GCLK_ID].bit.GEN = GEN_TC45;
195 pgclk->PCHCTRL[TC5_GCLK_ID].bit.CHEN = 1;
196
197 //configure TC4
198 DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN);
199 ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
200 while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE); }
201 ptc4->COUNT16.CTRLA.bit.SWRST = 1;
202 while (ptc4->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1); }
203 while (ptc4->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2); }
204
205 //CTRLA defaults
206 //CTRLB as default, counting up
207 ptc4->COUNT16.CTRLBCLR.reg = 5;
208 while (ptc4->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB); }
209 ptc4->COUNT16.CC[0].reg = 999;
210 while (ptc4->COUNT16.SYNCBUSY.bit.CC0) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0); }
211 //ptc4->COUNT16.DBGCTRL.bit.DBGRUN = 1;
212
213 //wave mode
214 ptc4->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
215 //generate event for next stage
216 ptc4->COUNT16.EVCTRL.bit.MCEO0 = 1;
217
218 NVIC_EnableIRQ(TC4_IRQn);
219 ptc4->COUNT16.INTENSET.bit.MC0 = 1;
220
221 DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE);
222
223 //configure TC5
224 DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN);
225 ptc5->COUNT16.CTRLA.bit.ENABLE = 0;
226 while (ptc5->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE); }
227 ptc5->COUNT16.CTRLA.bit.SWRST = 1;
228 while (ptc5->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1); }
229 while (ptc5->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2); }
230
231 //CTRLA defaults
232 //CTRLB as default, counting up
233 ptc5->COUNT16.CTRLBCLR.reg = 5;
234 while (ptc5->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB); }
235 //ptc5->COUNT16.DBGCTRL.bit.DBGRUN = 1;
236
237 //wave mode
238 ptc5->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
239 //generate event for next stage
240 ptc5->COUNT16.EVCTRL.bit.MCEO0 = 1;
241
242 NVIC_EnableIRQ(TC5_IRQn);
243 ptc5->COUNT16.INTENSET.bit.MC0 = 1;
244
245 DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE);
246
247 //unmask TC0,1, sourcegclk2 to TC0,1
248 pmclk->APBAMASK.bit.TC0_ = 1;
249 pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45;
250 pgclk->PCHCTRL[TC0_GCLK_ID].bit.CHEN = 1;
251
252 pmclk->APBAMASK.bit.TC1_ = 1;
253 pgclk->PCHCTRL[TC1_GCLK_ID].bit.GEN = GEN_TC45;
254 pgclk->PCHCTRL[TC1_GCLK_ID].bit.CHEN = 1;
255
256 //configure TC0
257 DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN);
258 ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
259 while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE); }
260 ptc0->COUNT32.CTRLA.bit.SWRST = 1;
261 while (ptc0->COUNT32.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1); }
262 while (ptc0->COUNT32.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2); }
263 //CTRLA as default
264 ptc0->COUNT32.CTRLA.bit.MODE = 2; //32 bit mode
265 ptc0->COUNT32.EVCTRL.bit.TCEI = 1; //enable incoming events
266 ptc0->COUNT32.EVCTRL.bit.EVACT = 2 ; //count events
267
268 DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE);
269
270 DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN);
271
272 //configure event system
273 pmclk->APBBMASK.bit.EVSYS_ = 1;
274 pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.GEN = GEN_TC45;
275 pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 1;
276 pevsys->USER[44].reg = EVSYS_ID_USER_PORT_EV_0; //TC0 will get event channel 0
277 pevsys->Channel[0].CHANNEL.bit.EDGSEL = EVSYS_CHANNEL_EDGSEL_RISING_EDGE_Val; //Rising edge
278 pevsys->Channel[0].CHANNEL.bit.PATH = EVSYS_CHANNEL_PATH_SYNCHRONOUS_Val; //Synchronous
279 pevsys->Channel[0].CHANNEL.bit.EVGEN = EVSYS_ID_GEN_TC4_MCX_0; //TC4 MC0
280
281 DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE);
282
283 CLK_reset_time();
284
285 ADC0_clock_init();
286
287 DBGC(DC_CLK_ENABLE_TIMEBASE_COMPLETE);
288
289 return 0;
290}
291
292uint32_t CLK_get_ms(void)
293{
294 return ms_clk;
295}
296
297void CLK_delay_us(uint16_t usec)
298{
299 us_delay_done = 0;
300
301 if (TC5->COUNT16.CTRLA.bit.ENABLE)
302 {
303 TC5->COUNT16.CTRLA.bit.ENABLE = 0;
304 while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
305 }
306
307 if (usec < 10) usec = 0;
308 else usec -= 10;
309
310 TC5->COUNT16.CC[0].reg = usec;
311 while (TC5->COUNT16.SYNCBUSY.bit.CC0) {}
312
313 TC5->COUNT16.CTRLA.bit.ENABLE = 1;
314 while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
315
316 while (!us_delay_done) {}
317}
318
319void CLK_delay_ms(uint64_t msec)
320{
321 msec += CLK_get_ms();
322 while (msec > CLK_get_ms()) {}
323}
324
325void clk_enable_sercom_apbmask(int sercomn)
326{
327 Mclk *pmclk = MCLK;
328 switch (sercomn)
329 {
330 case 0:
331 pmclk->APBAMASK.bit.SERCOM0_ = 1;
332 break;
333 case 1:
334 pmclk->APBAMASK.bit.SERCOM1_ = 1;
335 break;
336 case 2:
337 pmclk->APBBMASK.bit.SERCOM2_ = 1;
338 break;
339 case 3:
340 pmclk->APBBMASK.bit.SERCOM3_ = 1;
341 break;
342 default:
343 break;
344 }
345}
346
347//call CLK_oscctrl_init first
348//call CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
349uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq)
350{
351 DBGC(DC_CLK_SET_SPI_FREQ_BEGIN);
352
353 Gclk *pgclk = GCLK;
354 Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
355 clk_enable_sercom_apbmask(sercomn);
356
357 //all gclk0 for now
358 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
359 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
360
361 psercom->I2CM.CTRLA.bit.SWRST = 1;
362 while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
363 while (psercom->I2CM.CTRLA.bit.SWRST) {}
364
365 psercom->SPI.BAUD.reg = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
366 system_clks.freq_spi = system_clks.freq_gclk[0]/2/(psercom->SPI.BAUD.reg+1);
367 system_clks.freq_sercom[sercomn] = system_clks.freq_spi;
368
369 DBGC(DC_CLK_SET_SPI_FREQ_COMPLETE);
370
371 return system_clks.freq_spi;
372}
373
374//call CLK_oscctrl_init first
375//call CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
376uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq)
377{
378 DBGC(DC_CLK_SET_I2C0_FREQ_BEGIN);
379
380 Gclk *pgclk = GCLK;
381 Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
382 clk_enable_sercom_apbmask(sercomn);
383
384 //all gclk0 for now
385 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
386 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
387
388 psercom->I2CM.CTRLA.bit.SWRST = 1;
389 while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
390 while (psercom->I2CM.CTRLA.bit.SWRST) {}
391
392 psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
393 system_clks.freq_i2c0 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+1);
394 system_clks.freq_sercom[sercomn] = system_clks.freq_i2c0;
395
396 DBGC(DC_CLK_SET_I2C0_FREQ_COMPLETE);
397
398 return system_clks.freq_i2c0;
399}
400
401//call CLK_oscctrl_init first
402//call CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
403uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq)
404{
405 DBGC(DC_CLK_SET_I2C1_FREQ_BEGIN);
406
407 Gclk *pgclk = GCLK;
408 Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
409 clk_enable_sercom_apbmask(sercomn);
410
411 //all gclk0 for now
412 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
413 pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
414
415 psercom->I2CM.CTRLA.bit.SWRST = 1;
416 while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
417 while (psercom->I2CM.CTRLA.bit.SWRST) {}
418
419 psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-10);
420 system_clks.freq_i2c1 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+10);
421 system_clks.freq_sercom[sercomn] = system_clks.freq_i2c1;
422
423 DBGC(DC_CLK_SET_I2C1_FREQ_COMPLETE);
424
425 return system_clks.freq_i2c1;
426}
427
428void CLK_init(void)
429{
430 DBGC(DC_CLK_INIT_BEGIN);
431
432 memset((void *)&system_clks,0,sizeof(system_clks));
433
434 CLK_oscctrl_init();
435 CLK_enable_timebase();
436
437 DBGC(DC_CLK_INIT_COMPLETE);
438}
439
diff --git a/tmk_core/protocol/arm_atsam/clks.h b/tmk_core/protocol/arm_atsam/clks.h
new file mode 100644
index 000000000..96819bfdd
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/clks.h
@@ -0,0 +1,90 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _CLKS_H_
19#define _CLKS_H_
20
21#ifndef MD_BOOTLOADER
22
23//From keyboard
24#include "config_led.h"
25#include "config.h"
26
27#endif //MD_BOOTLOADER
28
29#define PLL_RATIO 47 //mcu frequency ((X+1)MHz)
30#define FREQ_DFLL_DEFAULT 48000000 //DFLL frequency / usb clock
31#define FREQ_SPI_DEFAULT 1000000 //spi to 595 shift regs
32#define FREQ_I2C0_DEFAULT 100000 //i2c to hub
33#define FREQ_I2C1_DEFAULT I2C_HZ //i2c to LED drivers
34#define FREQ_TC45_DEFAULT 1000000 //1 usec resolution
35
36//I2C1 Set ~Result PWM Time (2x Drivers)
37// 1000000 1090000
38// 900000 1000000 3.82ms
39// 800000 860000
40// 700000 750000
41// 600000 630000
42// 580000 615000 6.08ms
43// 500000 522000
44
45#define FREQ_XOSC0 16000000
46
47#define CHAN_SERCOM_SPI 2 //shift regs
48#define CHAN_SERCOM_I2C0 0 //hub
49#define CHAN_SERCOM_I2C1 1 //led drivers
50#define CHAN_SERCOM_UART 3 //debug util
51
52//Generator clock channels
53#define GEN_DPLL0 0
54#define GEN_OSC0 1
55#define GEN_TC45 2
56
57#define SERCOM_COUNT 5
58#define GCLK_COUNT 12
59
60typedef struct clk_s {
61 uint32_t freq_dfll;
62 uint32_t freq_dpll[2];
63 uint32_t freq_sercom[SERCOM_COUNT];
64 uint32_t freq_gclk[GCLK_COUNT];
65 uint32_t freq_xosc0;
66 uint32_t freq_spi;
67 uint32_t freq_i2c0;
68 uint32_t freq_i2c1;
69 uint32_t freq_uart;
70 uint32_t freq_adc0;
71} clk_t;
72
73extern volatile clk_t system_clks;
74extern volatile uint64_t ms_clk;
75
76void CLK_oscctrl_init(void);
77void CLK_reset_time(void);
78uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq);
79uint32_t CLK_enable_timebase(void);
80uint32_t CLK_get_ms(void);
81uint64_t CLK_get_us(void);
82void CLK_delay_us(uint16_t usec);
83void CLK_delay_ms(uint64_t msec);
84
85uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq);
86uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq);
87uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq);
88void CLK_init(void);
89
90#endif // _CLKS_H_
diff --git a/tmk_core/protocol/arm_atsam/d51_util.c b/tmk_core/protocol/arm_atsam/d51_util.c
new file mode 100644
index 000000000..91b58757c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/d51_util.c
@@ -0,0 +1,165 @@
1#include "d51_util.h"
2
3//Display unsigned 32-bit number through m15
4//Read as follows: 1230 = || ||| |||| | (note always ending toggle)
5void m15_print(uint32_t x)
6{
7 int8_t t;
8 uint32_t n;
9 uint32_t p, p2;
10
11 if (x < 10) t = 0;
12 else if (x < 100) t = 1;
13 else if (x < 1000) t = 2;
14 else if (x < 10000) t = 3;
15 else if (x < 100000) t = 4;
16 else if (x < 1000000) t = 5;
17 else if (x < 10000000) t = 6;
18 else if (x < 100000000) t = 7;
19 else if (x < 1000000000) t = 8;
20 else t = 9;
21
22 while (t >= 0)
23 {
24 p2 = t;
25 p = 1;
26 while (p2--) p *= 10;
27 n = x / p;
28 x -= n * p;
29 while (n > 0)
30 {
31 m15_on;
32 n--;
33 m15_off;
34 }
35 //Will always end with an extra toggle
36 m15_on;
37 t--;
38 m15_off;
39 }
40}
41
42//Display unsigned 32-bit number through debug led
43//Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash)
44#define DLED_ONTIME 600000
45#define DLED_PAUSE 1000000
46volatile uint32_t w;
47void dled_print(uint32_t x, uint8_t long_pause)
48{
49 int8_t t;
50 uint32_t n;
51 uint32_t p, p2;
52
53 if (x < 10) t = 0;
54 else if (x < 100) t = 1;
55 else if (x < 1000) t = 2;
56 else if (x < 10000) t = 3;
57 else if (x < 100000) t = 4;
58 else if (x < 1000000) t = 5;
59 else if (x < 10000000) t = 6;
60 else if (x < 100000000) t = 7;
61 else if (x < 1000000000) t = 8;
62 else t = 9;
63
64 while (t >= 0)
65 {
66 p2 = t;
67 p = 1;
68 while (p2--) p *= 10;
69 n = x / p;
70 x -= n * p;
71 if (!n)
72 {
73 led_on;
74 for (w = DLED_ONTIME / 4; w; w--);
75 led_off;
76 for (w = DLED_ONTIME / 4; w; w--);
77 led_on;
78 for (w = DLED_ONTIME / 4; w; w--);
79 led_off;
80 for (w = DLED_ONTIME / 4; w; w--);
81 n--;
82 }
83 else
84 {
85 while (n > 0)
86 {
87 led_on;
88 for (w = DLED_ONTIME; w; w--);
89 led_off;
90 for (w = DLED_ONTIME / 2; w; w--);
91 n--;
92 }
93 }
94
95 for (w = DLED_PAUSE; w; w--);
96 t--;
97 }
98
99 if (long_pause)
100 {
101 for (w = DLED_PAUSE * 4; w; w--);
102 }
103}
104
105#ifdef DEBUG_BOOT_TRACING
106
107volatile uint32_t debug_code;
108
109void EIC_15_Handler()
110{
111 //This is only for non-functional keyboard troubleshooting and should be disabled after boot
112 //Intention is to lock up the keyboard here with repeating debug led code
113 while (1)
114 {
115 dled_print(debug_code, 1);
116 }
117}
118
119void debug_code_init(void)
120{
121 DBGC(DC_UNSET);
122
123 //Configure Ports for EIC on PB31
124 PORT->Group[1].DIRCLR.reg = 1 << 31; //Input
125 PORT->Group[1].OUTSET.reg = 1 << 31; //High
126 PORT->Group[1].PINCFG[31].bit.INEN = 1; //Input Enable
127 PORT->Group[1].PINCFG[31].bit.PULLEN = 1; //Pull Enable
128 PORT->Group[1].PINCFG[31].bit.PMUXEN = 1; //Mux Enable
129 PORT->Group[1].PMUX[15].bit.PMUXO = 0; //Mux A
130
131 //Enable CLK_EIC_APB
132 MCLK->APBAMASK.bit.EIC_ = 1;
133
134 //Configure EIC
135 EIC->CTRLA.bit.SWRST = 1;
136 while (EIC->SYNCBUSY.bit.SWRST) {}
137 EIC->ASYNCH.reg = 1 << 15;
138 EIC->INTENSET.reg = 1 << 15;
139 EIC->CONFIG[1].bit.SENSE7 = 2;
140 EIC->CTRLA.bit.ENABLE = 1;
141 while (EIC->SYNCBUSY.bit.ENABLE) {}
142
143 //Enable EIC IRQ
144 NVIC_EnableIRQ(EIC_15_IRQn);
145}
146
147void debug_code_disable(void)
148{
149 //Disable EIC IRQ
150 NVIC_DisableIRQ(EIC_15_IRQn);
151
152 //Disable EIC
153 EIC->CTRLA.bit.ENABLE = 0;
154 while (EIC->SYNCBUSY.bit.ENABLE) {}
155
156 //Disable CLK_EIC_APB
157 MCLK->APBAMASK.bit.EIC_ = 0;
158}
159
160#else
161
162void debug_code_init(void) {}
163void debug_code_disable(void) {}
164
165#endif //DEBUG_BOOT_TRACING
diff --git a/tmk_core/protocol/arm_atsam/d51_util.h b/tmk_core/protocol/arm_atsam/d51_util.h
new file mode 100644
index 000000000..465889c7c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/d51_util.h
@@ -0,0 +1,185 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _D51_UTIL_H_
19#define _D51_UTIL_H_
20
21#include "samd51j18a.h"
22
23//TODO: PS: Should bring these ports out to keyboard level configuration
24
25//Debug LED PA27
26#define led_ena REG_PORT_DIRSET0 = 0x08000000 //PA27 Output
27#define led_on REG_PORT_OUTSET0 = 0x08000000 //PA27 High
28#define led_off REG_PORT_OUTCLR0 = 0x08000000 //PA27 Low
29
30//Debug Port PB30
31#define m15_ena REG_PORT_DIRSET1 = 0x40000000 //PB30 Output
32#define m15_on REG_PORT_OUTSET1 = 0x40000000 //PB30 High
33#define m15_off REG_PORT_OUTCLR1 = 0x40000000 //PB30 Low
34
35#define m15_loop(M15X) {uint8_t M15L=M15X; while(M15L--){m15_on;CLK_delay_us(1);m15_off;}}
36
37void m15_print(uint32_t x);
38void dled_print(uint32_t x, uint8_t long_pause);
39
40void debug_code_init(void);
41void debug_code_disable(void);
42
43#ifdef DEBUG_BOOT_TRACING
44
45#define DBGC(n) debug_code = n
46
47extern volatile uint32_t debug_code;
48
49enum debug_code_list {
50 DC_UNSET = 0,
51 DC_CLK_INIT_BEGIN,
52 DC_CLK_INIT_COMPLETE,
53 DC_CLK_SET_I2C1_FREQ_BEGIN,
54 DC_CLK_SET_I2C1_FREQ_COMPLETE,
55 DC_CLK_SET_I2C0_FREQ_BEGIN,
56 DC_CLK_SET_I2C0_FREQ_COMPLETE,
57 DC_CLK_SET_SPI_FREQ_BEGIN,
58 DC_CLK_SET_SPI_FREQ_COMPLETE,
59 DC_CLK_ENABLE_TIMEBASE_BEGIN,
60 DC_CLK_ENABLE_TIMEBASE_SYNC_ENABLE,
61 DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_1,
62 DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_2,
63 DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN,
64 DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE,
65 DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1,
66 DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2,
67 DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB,
68 DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0,
69 DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE,
70 DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN,
71 DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE,
72 DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1,
73 DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2,
74 DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB,
75 DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE,
76 DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN,
77 DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE,
78 DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1,
79 DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2,
80 DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE,
81 DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN,
82 DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE,
83 DC_CLK_ENABLE_TIMEBASE_COMPLETE,
84 DC_CLK_SET_GCLK_FREQ_BEGIN,
85 DC_CLK_SET_GCLK_FREQ_SYNC_1,
86 DC_CLK_SET_GCLK_FREQ_SYNC_2,
87 DC_CLK_SET_GCLK_FREQ_SYNC_3,
88 DC_CLK_SET_GCLK_FREQ_SYNC_4,
89 DC_CLK_SET_GCLK_FREQ_SYNC_5,
90 DC_CLK_SET_GCLK_FREQ_COMPLETE,
91 DC_CLK_INIT_OSC_BEGIN,
92 DC_CLK_INIT_OSC_SYNC_1,
93 DC_CLK_INIT_OSC_SYNC_2,
94 DC_CLK_INIT_OSC_SYNC_3,
95 DC_CLK_INIT_OSC_SYNC_4,
96 DC_CLK_INIT_OSC_SYNC_5,
97 DC_CLK_INIT_OSC_COMPLETE,
98 DC_CLK_RESET_TIME_BEGIN,
99 DC_CLK_RESET_TIME_COMPLETE,
100 DC_CLK_OSC_INIT_BEGIN,
101 DC_CLK_OSC_INIT_XOSC0_SYNC,
102 DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE,
103 DC_CLK_OSC_INIT_DPLL_SYNC_RATIO,
104 DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE,
105 DC_CLK_OSC_INIT_DPLL_WAIT_LOCK,
106 DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY,
107 DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0,
108 DC_CLK_OSC_INIT_COMPLETE,
109 DC_SPI_INIT_BEGIN,
110 DC_SPI_WRITE_DRE,
111 DC_SPI_WRITE_TXC_1,
112 DC_SPI_WRITE_TXC_2,
113 DC_SPI_SYNC_ENABLING,
114 DC_SPI_INIT_COMPLETE,
115 DC_PORT_DETECT_INIT_BEGIN,
116 DC_PORT_DETECT_INIT_FAILED,
117 DC_PORT_DETECT_INIT_COMPLETE,
118 DC_USB_RESET_BEGIN,
119 DC_USB_RESET_COMPLETE,
120 DC_USB_SET_HOST_BY_VOLTAGE_BEGIN,
121 DC_USB_SET_HOST_5V_LOW_WAITING,
122 DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE,
123 DC_USB_CONFIGURE_BEGIN,
124 DC_USB_CONFIGURE_GET_SERIAL,
125 DC_USB_CONFIGURE_COMPLETE,
126 DC_USB_WRITE2422_BLOCK_BEGIN,
127 DC_USB_WRITE2422_BLOCK_SYNC_SYSOP,
128 DC_USB_WRITE2422_BLOCK_COMPLETE,
129 DC_ADC0_CLOCK_INIT_BEGIN,
130 DC_ADC0_CLOCK_INIT_COMPLETE,
131 DC_ADC0_INIT_BEGIN,
132 DC_ADC0_SWRST_SYNCING_1,
133 DC_ADC0_SWRST_SYNCING_2,
134 DC_ADC0_AVGCTRL_SYNCING_1,
135 DC_ADC0_AVGCTRL_SYNCING_2,
136 DC_ADC0_SAMPCTRL_SYNCING_1,
137 DC_ADC0_ENABLE_SYNCING_1,
138 DC_ADC0_INIT_COMPLETE,
139 DC_I2C0_INIT_BEGIN,
140 DC_I2C0_INIT_SYNC_ENABLING,
141 DC_I2C0_INIT_SYNC_SYSOP,
142 DC_I2C0_INIT_WAIT_IDLE,
143 DC_I2C0_INIT_COMPLETE,
144 DC_I2C1_INIT_BEGIN,
145 DC_I2C1_INIT_SYNC_ENABLING,
146 DC_I2C1_INIT_SYNC_SYSOP,
147 DC_I2C1_INIT_WAIT_IDLE,
148 DC_I2C1_INIT_COMPLETE,
149 DC_I2C3733_INIT_CONTROL_BEGIN,
150 DC_I2C3733_INIT_CONTROL_COMPLETE,
151 DC_I2C3733_INIT_DRIVERS_BEGIN,
152 DC_I2C3733_INIT_DRIVERS_COMPLETE,
153 DC_I2C_DMAC_LED_INIT_BEGIN,
154 DC_I2C_DMAC_LED_INIT_COMPLETE,
155 DC_I2C3733_CONTROL_SET_BEGIN,
156 DC_I2C3733_CONTROL_SET_COMPLETE,
157 DC_LED_MATRIX_INIT_BEGIN,
158 DC_LED_MATRIX_INIT_COMPLETE,
159 DC_USB2422_INIT_BEGIN,
160 DC_USB2422_INIT_WAIT_5V_LOW,
161 DC_USB2422_INIT_OSC_SYNC_DISABLING,
162 DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1,
163 DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2,
164 DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3,
165 DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4,
166 DC_USB2422_INIT_OSC_SYNC_DFLLMUL,
167 DC_USB2422_INIT_OSC_SYNC_ENABLING,
168 DC_USB2422_INIT_USB_SYNC_SWRST,
169 DC_USB2422_INIT_USB_WAIT_SWRST,
170 DC_USB2422_INIT_USB_SYNC_ENABLING,
171 DC_USB2422_INIT_COMPLETE,
172 DC_MAIN_UDC_START_BEGIN,
173 DC_MAIN_UDC_START_COMPLETE,
174 DC_MAIN_CDC_INIT_BEGIN,
175 DC_MAIN_CDC_INIT_COMPLETE,
176 /* Never change the order of error codes! Only add codes to end! */
177};
178
179#else
180
181#define DBGC(n) {}
182
183#endif //DEBUG_BOOT_TRACING
184
185#endif //_D51_UTIL_H_
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c
new file mode 100644
index 000000000..bbe909e9b
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/i2c_master.c
@@ -0,0 +1,585 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20#ifndef MD_BOOTLOADER
21
22#include <string.h>
23
24//From keyboard
25#include "config.h"
26#include "config_led.h"
27#include "matrix.h"
28
29#define I2C_LED_USE_DMA 1 //Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers
30
31static uint8_t i2c_led_q[I2C_Q_SIZE]; //I2C queue circular buffer
32static uint8_t i2c_led_q_s; //Start of circular buffer
33static uint8_t i2c_led_q_e; //End of circular buffer
34static uint8_t i2c_led_q_full; //Queue full counter for reset
35
36static uint8_t dma_sendbuf[I2C_DMA_MAX_SEND]; //Data being written to I2C
37
38volatile uint8_t i2c_led_q_running;
39
40#endif //MD_BOOTLOADER
41
42void i2c0_init(void)
43{
44 DBGC(DC_I2C0_INIT_BEGIN);
45
46 CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
47
48 //MCU
49 PORT->Group[0].PMUX[4].bit.PMUXE = 2;
50 PORT->Group[0].PMUX[4].bit.PMUXO = 2;
51 PORT->Group[0].PINCFG[8].bit.PMUXEN = 1;
52 PORT->Group[0].PINCFG[9].bit.PMUXEN = 1;
53
54 //I2C
55 //Note: SW Reset handled in CLK_set_i2c0_freq clks.c
56
57 SERCOM0->I2CM.CTRLA.bit.MODE = 5; //Set master mode
58
59 SERCOM0->I2CM.CTRLA.bit.SPEED = 0; //Set to 1 for Fast-mode Plus (FM+) up to 1 MHz
60 SERCOM0->I2CM.CTRLA.bit.RUNSTDBY = 1; //Enabled
61
62 SERCOM0->I2CM.CTRLA.bit.ENABLE = 1; //Enable the device
63 while (SERCOM0->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C0_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
64
65 SERCOM0->I2CM.STATUS.bit.BUSSTATE = 1; //Force into IDLE state
66 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C0_INIT_SYNC_SYSOP); }
67 while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C0_INIT_WAIT_IDLE); } //Wait while not idle
68
69 DBGC(DC_I2C0_INIT_COMPLETE);
70}
71
72uint8_t i2c0_start(uint8_t address)
73{
74 SERCOM0->I2CM.ADDR.bit.ADDR = address;
75 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {}
76 while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
77 while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
78
79 return 1;
80}
81
82uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
83{
84 if (!length) return 0;
85
86 i2c0_start(address);
87
88 while (length)
89 {
90 SERCOM0->I2CM.DATA.bit.DATA = *data;
91 while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
92 while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
93
94 data++;
95 length--;
96 }
97
98 i2c0_stop();
99
100 return 1;
101}
102
103void i2c0_stop(void)
104{
105 if (SERCOM0->I2CM.STATUS.bit.CLKHOLD || SERCOM0->I2CM.INTFLAG.bit.MB == 1 || SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1)
106 {
107 SERCOM0->I2CM.CTRLB.bit.CMD = 3;
108 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP);
109 while (SERCOM0->I2CM.STATUS.bit.CLKHOLD);
110 while (SERCOM0->I2CM.INTFLAG.bit.MB);
111 while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1);
112 }
113}
114
115#ifndef MD_BOOTLOADER
116void i2c1_init(void)
117{
118 DBGC(DC_I2C1_INIT_BEGIN);
119
120 CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
121
122 /* MCU */
123 PORT->Group[0].PMUX[8].bit.PMUXE = 2;
124 PORT->Group[0].PMUX[8].bit.PMUXO = 2;
125 PORT->Group[0].PINCFG[16].bit.PMUXEN = 1;
126 PORT->Group[0].PINCFG[17].bit.PMUXEN = 1;
127
128 /* I2C */
129 //Note: SW Reset handled in CLK_set_i2c1_freq clks.c
130
131 SERCOM1->I2CM.CTRLA.bit.MODE = 5; //MODE: Set master mode (No sync)
132 SERCOM1->I2CM.CTRLA.bit.SPEED = 1; //SPEED: Fm+ up to 1MHz (No sync)
133 SERCOM1->I2CM.CTRLA.bit.RUNSTDBY = 1; //RUNSTBY: Enabled (No sync)
134
135 SERCOM1->I2CM.CTRLB.bit.SMEN = 1; //SMEN: Smart mode enabled (For DMA)(No sync)
136
137 NVIC_EnableIRQ(SERCOM1_0_IRQn);
138 SERCOM1->I2CM.INTENSET.bit.ERROR = 1;
139
140 SERCOM1->I2CM.CTRLA.bit.ENABLE = 1; //ENABLE: Enable the device (sync SYNCBUSY.ENABLE)
141 while (SERCOM1->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C1_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
142
143 SERCOM1->I2CM.STATUS.bit.BUSSTATE = 1; //BUSSTATE: Force into IDLE state (sync SYNCBUSY.SYSOP)
144 while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C1_INIT_SYNC_SYSOP); }
145 while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C1_INIT_WAIT_IDLE); } //Wait while not idle
146
147 DBGC(DC_I2C1_INIT_COMPLETE);
148}
149
150uint8_t i2c1_start(uint8_t address)
151{
152 SERCOM1->I2CM.ADDR.bit.ADDR = address;
153 while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) {}
154 while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
155 while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
156
157 return 1;
158}
159
160uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
161{
162 if (!length) return 0;
163
164 i2c1_start(address);
165
166 while (length)
167 {
168 SERCOM1->I2CM.DATA.bit.DATA = *data;
169 while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
170 while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
171
172 data++;
173 length--;
174 }
175
176 i2c1_stop();
177
178 return 1;
179}
180
181void i2c1_stop(void)
182{
183 if (SERCOM1->I2CM.STATUS.bit.CLKHOLD || SERCOM1->I2CM.INTFLAG.bit.MB == 1 || SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1)
184 {
185 SERCOM1->I2CM.CTRLB.bit.CMD = 3;
186 while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP);
187 while (SERCOM1->I2CM.STATUS.bit.CLKHOLD);
188 while (SERCOM1->I2CM.INTFLAG.bit.MB);
189 while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1);
190 }
191}
192
193void i2c_led_send_CRWL(uint8_t drvid)
194{
195 uint8_t i2cdata[] = { ISSI3733_CMDRWL, ISSI3733_CMDRWL_WRITE_ENABLE_ONCE };
196 i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
197}
198
199void i2c_led_select_page(uint8_t drvid, uint8_t pageno)
200{
201 uint8_t i2cdata[] = { ISSI3733_CMDR, pageno };
202 i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
203}
204
205void i2c_led_send_GCR(uint8_t drvid)
206{
207 uint8_t i2cdata[] = { ISSI3733_GCCR, 0x00 };
208
209 if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
210 i2cdata[1] = gcr_actual;
211
212 i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
213}
214
215void i2c_led_send_onoff(uint8_t drvid)
216{
217#if I2C_LED_USE_DMA != 1
218 if (!i2c_led_q_running)
219 {
220#endif
221 i2c_led_send_CRWL(drvid);
222 i2c_led_select_page(drvid, 0);
223#if I2C_LED_USE_DMA != 1
224 }
225#endif
226
227 *issidrv[drvid].onoff = 0; //Force start location offset to zero
228 i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].onoff, ISSI3733_PG0_BYTES, 0);
229}
230
231void i2c_led_send_mode_op_gcr(uint8_t drvid, uint8_t mode, uint8_t operation)
232{
233 uint8_t i2cdata[] = { ISSI3733_CR, mode | operation, gcr_actual};
234 i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
235}
236
237void i2c_led_send_pur_pdr(uint8_t drvid, uint8_t pur, uint8_t pdr)
238{
239 uint8_t i2cdata[] = { ISSI3733_SWYR_PUR, pur, pdr };
240
241 i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
242}
243
244void i2c_led_send_pwm(uint8_t drvid)
245{
246#if I2C_LED_USE_DMA != 1
247 if (!i2c_led_q_running)
248 {
249#endif
250 i2c_led_send_CRWL(drvid);
251 i2c_led_select_page(drvid, 0);
252#if I2C_LED_USE_DMA != 1
253 }
254#endif
255
256 *issidrv[drvid].pwm = 0; //Force start location offset to zero
257 i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].pwm, ISSI3733_PG1_BYTES, 0);
258}
259
260uint8_t I2C3733_Init_Control(void)
261{
262 DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
263
264 srdata.bit.SDB_N = 1;
265 SPI_WriteSRData();
266
267 CLK_delay_ms(1);
268
269 srdata.bit.IRST = 0;
270 SPI_WriteSRData();
271
272 CLK_delay_ms(1);
273
274 DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE);
275
276 return 1;
277}
278
279uint8_t I2C3733_Init_Drivers(void)
280{
281 DBGC(DC_I2C3733_INIT_DRIVERS_BEGIN);
282
283 gcr_actual = ISSI3733_GCR_DEFAULT;
284 gcr_actual_last = gcr_actual;
285
286 if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
287 gcr_desired = gcr_actual;
288
289 //Set up master device
290 i2c_led_send_CRWL(0);
291 i2c_led_select_page(0, 3);
292 i2c_led_send_mode_op_gcr(0, ISSI3733_CR_SYNC_MASTER, ISSI3733_CR_SSD_NORMAL);
293
294 //Set up slave device
295 i2c_led_send_CRWL(1);
296 i2c_led_select_page(1, 3);
297 i2c_led_send_mode_op_gcr(1, ISSI3733_CR_SYNC_SLAVE, ISSI3733_CR_SSD_NORMAL);
298
299 i2c_led_send_CRWL(0);
300 i2c_led_select_page(0, 3);
301 i2c_led_send_pur_pdr(0, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
302
303 i2c_led_send_CRWL(1);
304 i2c_led_select_page(1, 3);
305 i2c_led_send_pur_pdr(1, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
306
307 DBGC(DC_I2C3733_INIT_DRIVERS_COMPLETE);
308
309 return 1;
310}
311
312void I2C_DMAC_LED_Init(void)
313{
314 Dmac *dmac = DMAC;
315
316 DBGC(DC_I2C_DMAC_LED_INIT_BEGIN);
317
318 //Disable device
319 dmac->CTRL.bit.DMAENABLE = 0; //Disable DMAC
320 while (dmac->CTRL.bit.DMAENABLE) {} //Wait for disabled state in case of ongoing transfers
321 dmac->CTRL.bit.SWRST = 1; //Software Reset DMAC
322 while (dmac->CTRL.bit.SWRST) {} //Wait for software reset to complete
323
324 //Configure device
325 dmac->BASEADDR.reg = (uint32_t)&dmac_desc; //Set descriptor base address
326 dmac->WRBADDR.reg = (uint32_t)&dmac_desc_wb; //Set descriptor write back address
327 dmac->CTRL.reg |= 0x0f00; //Handle all priorities (LVL0-3)
328
329 //Disable channel
330 dmac->Channel[0].CHCTRLA.bit.ENABLE = 0; //Disable the channel
331 while (dmac->Channel[0].CHCTRLA.bit.ENABLE) {} //Wait for disabled state in case of ongoing transfers
332 dmac->Channel[0].CHCTRLA.bit.SWRST = 1; //Software Reset the channel
333 while (dmac->Channel[0].CHCTRLA.bit.SWRST) {} //Wait for software reset to complete
334
335 //Configure channel
336 dmac->Channel[0].CHCTRLA.bit.THRESHOLD = 0; //1BEAT
337 dmac->Channel[0].CHCTRLA.bit.BURSTLEN = 0; //SINGLE
338 dmac->Channel[0].CHCTRLA.bit.TRIGACT = 2; //BURST
339 dmac->Channel[0].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_TX; //Trigger source
340 dmac->Channel[0].CHCTRLA.bit.RUNSTDBY = 1; //Run in standby
341
342 NVIC_EnableIRQ(DMAC_0_IRQn);
343 dmac->Channel[0].CHINTENSET.bit.TCMPL = 1;
344 dmac->Channel[0].CHINTENSET.bit.TERR = 1;
345
346 //Enable device
347 dmac->CTRL.bit.DMAENABLE = 1; //Enable DMAC
348 while (dmac->CTRL.bit.DMAENABLE == 0) {} //Wait for enable state
349
350 DBGC(DC_I2C_DMAC_LED_INIT_COMPLETE);
351}
352
353//state = 1 enable
354//state = 0 disable
355void I2C3733_Control_Set(uint8_t state)
356{
357 DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
358
359 srdata.bit.SDB_N = (state == 1 ? 1 : 0);
360 SPI_WriteSRData();
361
362 DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
363}
364
365void i2c_led_desc_defaults(void)
366{
367 dmac_desc.BTCTRL.bit.STEPSIZE = 0; //SRCINC used in favor for auto 1 inc
368 dmac_desc.BTCTRL.bit.STEPSEL = 0; //SRCINC used in favor for auto 1 inc
369 dmac_desc.BTCTRL.bit.DSTINC = 0; //The Destination Address Increment is disabled
370 dmac_desc.BTCTRL.bit.SRCINC = 1; //The Source Address Increment is enabled (Inc by 1)
371 dmac_desc.BTCTRL.bit.BEATSIZE = 0; //8-bit bus transfer
372 dmac_desc.BTCTRL.bit.BLOCKACT = 0; //Channel will be disabled if it is the last block transfer in the transaction
373 dmac_desc.BTCTRL.bit.EVOSEL = 0; //Event generation disabled
374 dmac_desc.BTCTRL.bit.VALID = 1; //Set dmac valid
375}
376
377void i2c_led_prepare_send_dma(uint8_t *data, uint8_t len)
378{
379 i2c_led_desc_defaults();
380
381 dmac_desc.BTCNT.reg = len;
382 dmac_desc.SRCADDR.reg = (uint32_t)data + len;
383 dmac_desc.DSTADDR.reg = (uint32_t)&SERCOM1->I2CM.DATA.reg;
384 dmac_desc.DESCADDR.reg = 0;
385}
386
387void i2c_led_begin_dma(uint8_t drvid)
388{
389 DMAC->Channel[0].CHCTRLA.bit.ENABLE = 1; //Enable the channel
390
391 SERCOM1->I2CM.ADDR.reg = (dmac_desc.BTCNT.reg << 16) | 0x2000 | issidrv[drvid].addr; //Begin transfer
392}
393
394void i2c_led_send_CRWL_dma(uint8_t drvid)
395{
396 *(dma_sendbuf+0) = ISSI3733_CMDRWL;
397 *(dma_sendbuf+1) = ISSI3733_CMDRWL_WRITE_ENABLE_ONCE;
398 i2c_led_prepare_send_dma(dma_sendbuf, 2);
399
400 i2c_led_begin_dma(drvid);
401}
402
403void i2c_led_select_page_dma(uint8_t drvid, uint8_t pageno)
404{
405 *(dma_sendbuf+0) = ISSI3733_CMDR;
406 *(dma_sendbuf+1) = pageno;
407 i2c_led_prepare_send_dma(dma_sendbuf, 2);
408
409 i2c_led_begin_dma(drvid);
410}
411
412void i2c_led_send_GCR_dma(uint8_t drvid)
413{
414 *(dma_sendbuf+0) = ISSI3733_GCCR;
415 *(dma_sendbuf+1) = gcr_actual;
416 i2c_led_prepare_send_dma(dma_sendbuf, 2);
417
418 i2c_led_begin_dma(drvid);
419}
420
421void i2c_led_send_pwm_dma(uint8_t drvid)
422{
423 //Note: This copies the CURRENT pwm buffer, which may be getting modified
424 memcpy(dma_sendbuf, issidrv[drvid].pwm, ISSI3733_PG1_BYTES);
425 *dma_sendbuf = 0; //Force start location offset to zero
426 i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG1_BYTES);
427
428 i2c_led_begin_dma(drvid);
429}
430
431void i2c_led_send_onoff_dma(uint8_t drvid)
432{
433 //Note: This copies the CURRENT onoff buffer, which may be getting modified
434 memcpy(dma_sendbuf, issidrv[drvid].onoff, ISSI3733_PG0_BYTES);
435 *dma_sendbuf = 0; //Force start location offset to zero
436 i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG0_BYTES);
437
438 i2c_led_begin_dma(drvid);
439}
440
441void i2c_led_q_init(void)
442{
443 memset(i2c_led_q, 0, I2C_Q_SIZE);
444 i2c_led_q_s = 0;
445 i2c_led_q_e = 0;
446 i2c_led_q_running = 0;
447 i2c_led_q_full = 0;
448}
449
450uint8_t i2c_led_q_isempty(void)
451{
452 return i2c_led_q_s == i2c_led_q_e;
453}
454
455uint8_t i2c_led_q_size(void)
456{
457 return (i2c_led_q_e - i2c_led_q_s) % I2C_Q_SIZE;
458}
459
460uint8_t i2c_led_q_available(void)
461{
462 return I2C_Q_SIZE - i2c_led_q_size() - 1; //Never allow end to meet start
463}
464
465void i2c_led_q_add(uint8_t cmd)
466{
467 //WARNING: Always request room before adding commands!
468
469 //Assign command
470 i2c_led_q[i2c_led_q_e] = cmd;
471
472 i2c_led_q_e = (i2c_led_q_e + 1) % I2C_Q_SIZE; //Move end up one or wrap
473}
474
475void i2c_led_q_s_advance(void)
476{
477 i2c_led_q_s = (i2c_led_q_s + 1) % I2C_Q_SIZE; //Move start up one or wrap
478}
479
480//Always request room before adding commands
481//PS: In case the queue somehow gets filled, it will reset if it can not clear up
482//PS: Could only get this to happen through unrealistic timings to overload the I2C bus
483uint8_t i2c_led_q_request_room(uint8_t request_size)
484{
485 if (request_size > i2c_led_q_available())
486 {
487 i2c_led_q_full++;
488
489 if (i2c_led_q_full >= 100) //Give the queue a chance to clear up
490 {
491 led_on;
492 I2C_DMAC_LED_Init();
493 i2c_led_q_init();
494 return 1;
495 }
496
497 return 0;
498 }
499
500 i2c_led_q_full = 0;
501
502 return 1;
503}
504
505uint8_t i2c_led_q_run(void)
506{
507 if (i2c_led_q_isempty())
508 {
509 i2c_led_q_running = 0;
510 return 0;
511 }
512
513 if (i2c_led_q_running) return 1;
514
515 i2c_led_q_running = 1;
516
517#if I2C_LED_USE_DMA != 1
518 while (!i2c_led_q_isempty())
519 {
520#endif
521 //run command
522 if (i2c_led_q[i2c_led_q_s] == I2C_Q_CRWL)
523 {
524 i2c_led_q_s_advance();
525 uint8_t drvid = i2c_led_q[i2c_led_q_s];
526#if I2C_LED_USE_DMA == 1
527 i2c_led_send_CRWL_dma(drvid);
528#else
529 i2c_led_send_CRWL(drvid);
530#endif
531 }
532 else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PAGE_SELECT)
533 {
534 i2c_led_q_s_advance();
535 uint8_t drvid = i2c_led_q[i2c_led_q_s];
536 i2c_led_q_s_advance();
537 uint8_t page = i2c_led_q[i2c_led_q_s];
538#if I2C_LED_USE_DMA == 1
539 i2c_led_select_page_dma(drvid, page);
540#else
541 i2c_led_select_page(drvid, page);
542#endif
543 }
544 else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PWM)
545 {
546 i2c_led_q_s_advance();
547 uint8_t drvid = i2c_led_q[i2c_led_q_s];
548#if I2C_LED_USE_DMA == 1
549 i2c_led_send_pwm_dma(drvid);
550#else
551 i2c_led_send_pwm(drvid);
552#endif
553 }
554 else if (i2c_led_q[i2c_led_q_s] == I2C_Q_GCR)
555 {
556 i2c_led_q_s_advance();
557 uint8_t drvid = i2c_led_q[i2c_led_q_s];
558#if I2C_LED_USE_DMA == 1
559 i2c_led_send_GCR_dma(drvid);
560#else
561 i2c_led_send_GCR(drvid);
562#endif
563 }
564 else if (i2c_led_q[i2c_led_q_s] == I2C_Q_ONOFF)
565 {
566 i2c_led_q_s_advance();
567 uint8_t drvid = i2c_led_q[i2c_led_q_s];
568#if I2C_LED_USE_DMA == 1
569 i2c_led_send_onoff_dma(drvid);
570#else
571 i2c_led_send_onoff(drvid);
572#endif
573 }
574
575 i2c_led_q_s_advance(); //Advance last run command or if the command byte was not serviced
576
577#if I2C_LED_USE_DMA != 1
578 }
579
580 i2c_led_q_running = 0;
581#endif
582
583 return 1;
584}
585#endif //MD_BOOTLOADER
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h
new file mode 100644
index 000000000..99481366a
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/i2c_master.h
@@ -0,0 +1,108 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _I2C_MASTER_H_
19#define _I2C_MASTER_H_
20
21#ifndef MD_BOOTLOADER
22
23#include "samd51j18a.h"
24#include "issi3733_driver.h"
25#include "config.h"
26
27__attribute__((__aligned__(16)))
28DmacDescriptor dmac_desc;
29__attribute__((__aligned__(16)))
30DmacDescriptor dmac_desc_wb;
31
32uint8_t I2C3733_Init_Control(void);
33uint8_t I2C3733_Init_Drivers(void);
34void I2C3733_Control_Set(uint8_t state);
35void I2C_DMAC_LED_Init(void);
36
37#define I2C_Q_SIZE 100
38
39#define I2C_Q_NA 100
40#define I2C_Q_CRWL 101
41#define I2C_Q_PAGE_SELECT 102
42#define I2C_Q_PWM 103
43#define I2C_Q_GCR 104
44#define I2C_Q_ONOFF 105
45
46#define I2C_DMA_MAX_SEND 255
47
48extern volatile uint8_t i2c_led_q_running;
49
50#define I2C_LED_Q_PWM(a) { \
51 if (i2c_led_q_request_room(7)) \
52 { \
53 i2c_led_q_add(I2C_Q_CRWL); \
54 i2c_led_q_add(a); \
55 i2c_led_q_add(I2C_Q_PAGE_SELECT); \
56 i2c_led_q_add(a); \
57 i2c_led_q_add(ISSI3733_PG_PWM); \
58 i2c_led_q_add(I2C_Q_PWM); \
59 i2c_led_q_add(a); \
60 } \
61 }
62
63#define I2C_LED_Q_GCR(a) { \
64 if (i2c_led_q_request_room(7)) \
65 { \
66 i2c_led_q_add(I2C_Q_CRWL); \
67 i2c_led_q_add(a); \
68 i2c_led_q_add(I2C_Q_PAGE_SELECT); \
69 i2c_led_q_add(a); \
70 i2c_led_q_add(ISSI3733_PG_FN); \
71 i2c_led_q_add(I2C_Q_GCR); \
72 i2c_led_q_add(a); \
73 } \
74 }
75
76#define I2C_LED_Q_ONOFF(a) { \
77 if (i2c_led_q_request_room(7)) \
78 { \
79 i2c_led_q_add(I2C_Q_CRWL); \
80 i2c_led_q_add(a); \
81 i2c_led_q_add(I2C_Q_PAGE_SELECT); \
82 i2c_led_q_add(a); \
83 i2c_led_q_add(ISSI3733_PG_ONOFF); \
84 i2c_led_q_add(I2C_Q_ONOFF); \
85 i2c_led_q_add(a); \
86 } \
87 }
88
89
90void i2c_led_q_init(void);
91void i2c_led_q_add(uint8_t cmd);
92void i2c_led_q_s_advance(void);
93uint8_t i2c_led_q_size(void);
94uint8_t i2c_led_q_request_room(uint8_t request_size);
95uint8_t i2c_led_q_run(void);
96
97void i2c1_init(void);
98uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
99void i2c1_stop(void);
100
101#endif //MD_BOOTLOADER
102
103void i2c0_init(void);
104uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
105void i2c0_stop(void);
106
107#endif // _I2C_MASTER_H_
108
diff --git a/tmk_core/protocol/arm_atsam/issi3733_driver.h b/tmk_core/protocol/arm_atsam/issi3733_driver.h
new file mode 100644
index 000000000..a537029f0
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/issi3733_driver.h
@@ -0,0 +1,201 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _ISSI3733_DRIVER_H_
19#define _ISSI3733_DRIVER_H_
20
21//ISII3733 Registers
22
23#define ISSI3733_CMDR 0xFD //Command Register (Write Only)
24
25#define ISSI3733_CMDRWL 0xFE //Command Register Write Lock (Read/Write)
26#define ISSI3733_CMDRWL_WRITE_DISABLE 0x00 //Lock register
27#define ISSI3733_CMDRWL_WRITE_ENABLE_ONCE 0xC5 //Enable one write to register then reset to locked
28
29#define ISSI3733_IMR 0xF0 //Interrupt Mask Register (Write Only)
30#define ISSI3733_IMR_IAC_ON 0x08 //Auto Clear Interrupt Bit - Interrupt auto clear when INTB stay low exceeds 8ms
31#define ISSI3733_IMR_IAB_ON 0x04 //Auto Breath Interrupt Bit - Enable auto breath loop finish interrupt
32#define ISSI3733_IMR_IS_ON 0x02 //Dot Short Interrupt Bit - Enable dot short interrupt
33#define ISSI3733_IMR_IO_ON 0x01 //Dot Open Interrupt Bit - Enable dot open interrupt
34
35#define ISSI3733_ISR 0xF1 //Interrupt Status Register (Read Only)
36#define ISSI3733_ISR_ABM3_FINISH 0x10 //Auto Breath Mode 3 Finish Bit - ABM3 finished
37#define ISSI3733_ISR_ABM2_FINISH 0x08 //Auto Breath Mode 2 Finish Bit - ABM2 finished
38#define ISSI3733_ISR_ABM1_FINISH 0x04 //Auto Breath Mode 1 Finish Bit - ABM1 finished
39#define ISSI3733_ISR_SB 0x02 //Short Bit - Shorted
40#define ISSI3733_ISR_OB 0x01 //Open Bit - Opened
41
42#define ISSI3733_PG0 0x00 //LED Control Register
43#define ISSI3733_PG1 0x01 //PWM Register
44#define ISSI3733_PG2 0x02 //Auto Breath Mode Register
45#define ISSI3733_PG3 0x03 //Function Register
46
47#define ISSI3733_PG_ONOFF ISSI3733_PG0
48#define ISSI3733_PG_OR ISSI3733_PG0
49#define ISSI3733_PG_SR ISSI3733_PG0
50#define ISSI3733_PG_PWM ISSI3733_PG1
51#define ISSI3733_PG_ABM ISSI3733_PG2
52#define ISSI3733_PG_FN ISSI3733_PG3
53
54#define ISSI3733_CR 0x00 //Configuration Register
55
56//PG3: Configuration Register: Synchronize Configuration
57#define ISSI3733_CR_SYNC_MASTER 0x40 //Master
58#define ISSI3733_CR_SYNC_SLAVE 0x80 //Slave
59#define ISSI3733_CR_SYNC_HIGH_IMP 0xC0 //High Impedance
60
61//PG3: Configuration Register: Open/Short Detection Enable Bit
62//#define ISSI3733_CR_OSD_DISABLE 0x00 //Disable open/short detection
63#define ISSI3733_CR_OSD_ENABLE 0x04 //Enable open/short detection
64
65//PG3: Configuration Register: Auto Breath Enable
66//#define ISSI3733_CR_B_EN_PWM 0x00 //PWM Mode Enable
67#define ISSI3733_CR_B_EN_AUTO 0x02 //Auto Breath Mode Enable
68
69//PG3: Configuration Register: Software Shutdown Control
70//#define ISSI3733_CR_SSD_SHUTDOWN 0x00 //Software shutdown
71#define ISSI3733_CR_SSD_NORMAL 0x01 //Normal operation
72
73#define ISSI3733_GCCR 0x01 //Global Current Control Register
74
75//1 Byte, Iout = (GCC / 256) * (840 / Rext)
76//TODO: Give user define for Rext
77
78//PG3: Auto Breath Control Register 1
79#define ISSI3733_ABCR1_ABM1 0x02 //Auto Breath Control Register 1 of ABM-1
80#define ISSI3733_ABCR1_ABM2 0x06 //Auto Breath Control Register 1 of ABM-2
81#define ISSI3733_ABCR1_ABM3 0x0A //Auto Breath Control Register 1 of ABM-3
82
83//Rise time
84#define ISSI3733_ABCR1_T1_0021 0x00 //0.21s
85#define ISSI3733_ABCR1_T1_0042 0x20 //0.42s
86#define ISSI3733_ABCR1_T1_0084 0x40 //0.84s
87#define ISSI3733_ABCR1_T1_0168 0x60 //1.68s
88#define ISSI3733_ABCR1_T1_0336 0x80 //3.36s
89#define ISSI3733_ABCR1_T1_0672 0xA0 //6.72s
90#define ISSI3733_ABCR1_T1_1344 0xC0 //13.44s
91#define ISSI3733_ABCR1_T1_2688 0xE0 //26.88s
92
93//Max value time
94#define ISSI3733_ABCR1_T2_0000 0x00 //0s
95#define ISSI3733_ABCR1_T2_0021 0x02 //0.21s
96#define ISSI3733_ABCR1_T2_0042 0x04 //0.42s
97#define ISSI3733_ABCR1_T2_0084 0x06 //0.84s
98#define ISSI3733_ABCR1_T2_0168 0x08 //1.68s
99#define ISSI3733_ABCR1_T2_0336 0x0A //3.36s
100#define ISSI3733_ABCR1_T2_0672 0x0C //6.72s
101#define ISSI3733_ABCR1_T2_1344 0x0E //13.44s
102#define ISSI3733_ABCR1_T2_2688 0x10 //26.88s
103
104//PG3: Auto Breath Control Register 2
105#define ISSI3733_ABCR2_ABM1 0x03 //Auto Breath Control Register 2 of ABM-1
106#define ISSI3733_ABCR2_ABM2 0x07 //Auto Breath Control Register 2 of ABM-2
107#define ISSI3733_ABCR2_ABM3 0x0B //Auto Breath Control Register 2 of ABM-3
108
109//Fall time
110#define ISSI3733_ABCR2_T3_0021 0x00 //0.21s
111#define ISSI3733_ABCR2_T3_0042 0x20 //0.42s
112#define ISSI3733_ABCR2_T3_0084 0x40 //0.84s
113#define ISSI3733_ABCR2_T3_0168 0x60 //1.68s
114#define ISSI3733_ABCR2_T3_0336 0x80 //3.36s
115#define ISSI3733_ABCR2_T3_0672 0xA0 //6.72s
116#define ISSI3733_ABCR2_T3_1344 0xC0 //13.44s
117#define ISSI3733_ABCR2_T3_2688 0xE0 //26.88s
118
119//Min value time
120#define ISSI3733_ABCR2_T4_0000 0x00 //0s
121#define ISSI3733_ABCR2_T4_0021 0x02 //0.21s
122#define ISSI3733_ABCR2_T4_0042 0x04 //0.42s
123#define ISSI3733_ABCR2_T4_0084 0x06 //0.84s
124#define ISSI3733_ABCR2_T4_0168 0x08 //1.68s
125#define ISSI3733_ABCR2_T4_0336 0x0A //3.36s
126#define ISSI3733_ABCR2_T4_0672 0x0C //6.72s
127#define ISSI3733_ABCR2_T4_1344 0x0E //13.44s
128#define ISSI3733_ABCR2_T4_2688 0x10 //26.88s
129#define ISSI3733_ABCR2_T4_5376 0x12 //53.76s
130#define ISSI3733_ABCR2_T4_10752 0x14 //107.52s
131
132//PG3: Auto Breath Control Register 3
133#define ISSI3733_ABCR3_ABM1 0x04 //Auto Breath Control Register 3 of ABM-1
134#define ISSI3733_ABCR3_ABM2 0x08 //Auto Breath Control Register 3 of ABM-2
135#define ISSI3733_ABCR3_ABM3 0x0C //Auto Breath Control Register 3 of ABM-3
136
137#define ISSI3733_ABCR3_LTA_LOOP_ENDLESS 0x00
138#define ISSI3733_ABCR3_LTA_LOOP_1 0x01
139#define ISSI3733_ABCR3_LTA_LOOP_2 0x02
140#define ISSI3733_ABCR3_LTA_LOOP_3 0x03
141#define ISSI3733_ABCR3_LTA_LOOP_4 0x04
142#define ISSI3733_ABCR3_LTA_LOOP_5 0x05
143#define ISSI3733_ABCR3_LTA_LOOP_6 0x06
144#define ISSI3733_ABCR3_LTA_LOOP_7 0x07
145#define ISSI3733_ABCR3_LTA_LOOP_8 0x08
146#define ISSI3733_ABCR3_LTA_LOOP_9 0x09
147#define ISSI3733_ABCR3_LTA_LOOP_10 0x0A
148#define ISSI3733_ABCR3_LTA_LOOP_11 0x0B
149#define ISSI3733_ABCR3_LTA_LOOP_12 0x0C
150#define ISSI3733_ABCR3_LTA_LOOP_13 0x0D
151#define ISSI3733_ABCR3_LTA_LOOP_14 0x0E
152#define ISSI3733_ABCR3_LTA_LOOP_15 0x0F
153
154//Loop Begin
155#define ISSI3733_ABCR3_LB_T1 0x00
156#define ISSI3733_ABCR3_LB_T2 0x10
157#define ISSI3733_ABCR3_LB_T3 0x20
158#define ISSI3733_ABCR3_LB_T4 0x30
159
160//Loop End
161#define ISSI3733_ABCR3_LE_T3 0x00 //End at Off state
162#define ISSI3733_ABCR3_LE_T1 0x40 //End at On State
163
164//PG3: Auto Breath Control Register 4
165#define ISSI3733_ABCR4_ABM1 0x05 //Auto Breath Control Register 4 of ABM-1
166#define ISSI3733_ABCR4_ABM2 0x09 //Auto Breath Control Register 4 of ABM-2
167#define ISSI3733_ABCR4_ABM3 0x0D //Auto Breath Control Register 4 of ABM-3
168
169#define ISSI3733_ABCR4_LTB_LOOP_ENDLESS 0x00
170//Or 8bit loop times
171
172//PG3: Time Update Register
173#define ISSI3733_TUR 0x0E
174#define ISSI3733_TUR_UPDATE 0x00 //Write to update 02h~0Dh time registers after configuring
175
176//PG3: SWy Pull-Up Resistor Selection Register
177#define ISSI3733_SWYR_PUR 0x0F
178#define ISSI3733_SWYR_PUR_NONE 0x00 //No pull-up resistor
179#define ISSI3733_SWYR_PUR_500 0x01 //0.5k Ohm
180#define ISSI3733_SWYR_PUR_1000 0x02 //1.0k Ohm
181#define ISSI3733_SWYR_PUR_2000 0x03 //2.0k Ohm
182#define ISSI3733_SWYR_PUR_4000 0x04 //4.0k Ohm
183#define ISSI3733_SWYR_PUR_8000 0x05 //8.0k Ohm
184#define ISSI3733_SWYR_PUR_16000 0x06 //16k Ohm
185#define ISSI3733_SWYR_PUR_32000 0x07 //32k Ohm
186
187//PG3: CSx Pull-Down Resistor Selection Register
188#define ISSI3733_CSXR_PDR 0x10
189#define ISSI3733_CSXR_PDR_NONE 0x00 //No pull-down resistor
190#define ISSI3733_CSXR_PDR_500 0x01 //0.5k Ohm
191#define ISSI3733_CSXR_PDR_1000 0x02 //1.0k Ohm
192#define ISSI3733_CSXR_PDR_2000 0x03 //2.0k Ohm
193#define ISSI3733_CSXR_PDR_4000 0x04 //4.0k Ohm
194#define ISSI3733_CSXR_PDR_8000 0x05 //8.0k Ohm
195#define ISSI3733_CSXR_PDR_16000 0x06 //16k Ohm
196#define ISSI3733_CSXR_PDR_32000 0x07 //32k Ohm
197
198//PG3: Reset Register
199#define ISSI3733_RR 0x11 //Read to reset all registers to default values
200
201#endif //_ISSI3733_DRIVER_H_
diff --git a/tmk_core/protocol/arm_atsam/led_matrix.c b/tmk_core/protocol/arm_atsam/led_matrix.c
new file mode 100644
index 000000000..7ee1dad22
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/led_matrix.c
@@ -0,0 +1,509 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19#include "tmk_core/common/led.h"
20#include <string.h>
21
22void SERCOM1_0_Handler( void )
23{
24 if (SERCOM1->I2CM.INTFLAG.bit.ERROR)
25 {
26 SERCOM1->I2CM.INTFLAG.reg = SERCOM_I2CM_INTENCLR_ERROR;
27 }
28}
29
30void DMAC_0_Handler( void )
31{
32 if (DMAC->Channel[0].CHINTFLAG.bit.TCMPL)
33 {
34 DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
35
36 i2c1_stop();
37
38 i2c_led_q_running = 0;
39
40 i2c_led_q_run();
41
42 return;
43 }
44
45 if (DMAC->Channel[0].CHINTFLAG.bit.TERR)
46 {
47 DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
48 }
49}
50
51issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
52
53issi3733_led_t led_map[ISSI3733_LED_COUNT+1] = ISSI3733_LED_MAP;
54issi3733_led_t *lede = led_map + ISSI3733_LED_COUNT; //End pointer of mapping
55
56uint8_t gcr_desired;
57uint8_t gcr_breathe;
58uint8_t gcr_use;
59uint8_t gcr_actual;
60uint8_t gcr_actual_last;
61
62#define ACT_GCR_NONE 0
63#define ACT_GCR_INC 1
64#define ACT_GCR_DEC 2
65
66#define LED_GCR_STEP_AUTO 2
67
68static uint8_t gcr_min_counter;
69static uint8_t v_5v_cat_hit;
70
71//WARNING: Automatic GCR is in place to prevent USB shutdown and LED driver overloading
72void gcr_compute(void)
73{
74 uint8_t action = ACT_GCR_NONE;
75
76 if (led_animation_breathing)
77 gcr_use = gcr_breathe;
78 else
79 gcr_use = gcr_desired;
80
81 //If the 5v takes a catastrophic hit, disable the LED drivers briefly, assert auto gcr mode, min gcr and let the auto take over
82 if (v_5v < V5_CAT)
83 {
84 I2C3733_Control_Set(0);
85 //CDC_print("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\r\n"); //Blocking print is bad here!
86 v_5v_cat_hit = 20; //~100ms recover
87 gcr_actual = 0; //Minimize GCR
88 usb_gcr_auto = 1; //Force auto mode enabled
89 return;
90 }
91 else if (v_5v_cat_hit > 1)
92 {
93 v_5v_cat_hit--;
94 return;
95 }
96 else if (v_5v_cat_hit == 1)
97 {
98 I2C3733_Control_Set(1);
99 CDC_print("USB: WARNING: Re-enabling LED drivers\r\n");
100 v_5v_cat_hit = 0;
101 return;
102 }
103
104 if (usb_gcr_auto)
105 {
106 if (v_5v_avg < V5_LOW) action = ACT_GCR_DEC;
107 else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use) action = ACT_GCR_INC;
108 else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
109 }
110 else
111 {
112 if (gcr_actual < gcr_use) action = ACT_GCR_INC;
113 else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
114 }
115
116 if (action == ACT_GCR_NONE)
117 {
118 gcr_min_counter = 0;
119 }
120 else if (action == ACT_GCR_INC)
121 {
122 if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual) gcr_actual = LED_GCR_MAX; //Obey max and prevent wrapping
123 else gcr_actual += LED_GCR_STEP_AUTO;
124 gcr_min_counter = 0;
125 }
126 else if (action == ACT_GCR_DEC)
127 {
128 if (LED_GCR_STEP_AUTO > gcr_actual) //Prevent wrapping
129 {
130 gcr_actual = 0;
131 //At this point, power can no longer be cut from the LED drivers, so focus on cutting out extra port if active
132 if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) //If not in a wait for replug state
133 {
134 if (usb_extra_state == USB_EXTRA_STATE_ENABLED) //If extra usb is enabled
135 {
136 gcr_min_counter++;
137 if (gcr_min_counter > 200) //5ms per check = 1s delay
138 {
139 USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG);
140 usb_extra_manual = 0; //Force disable manual mode of extra port
141 if (usb_extra_manual) CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n");
142 else CDC_print("USB: Disabling extra port until replug!\r\n");
143 }
144 }
145 }
146 }
147 else
148 {
149 //Power successfully cut back from LED drivers
150 gcr_actual -= LED_GCR_STEP_AUTO;
151 gcr_min_counter = 0;
152
153 //If breathe mode is active, the top end can fluctuate if the host can not supply enough current
154 //So set the breathe GCR to where it becomes stable
155 if (led_animation_breathing == 1)
156 {
157 gcr_breathe = gcr_actual;
158 //PS: At this point, setting breathing to exhale makes a noticebly shorter cycle
159 // and the same would happen maybe one or two more times. Therefore I'm favoring
160 // powering through one full breathe and letting gcr settle completely
161 }
162 }
163 }
164}
165
166led_disp_t disp;
167
168void issi3733_prepare_arrays(void)
169{
170 memset(issidrv,0,sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT);
171
172 int i;
173 uint8_t addrs[ISSI3733_DRIVER_COUNT] = ISSI3773_DRIVER_ADDRESSES;
174
175 for (i=0;i<ISSI3733_DRIVER_COUNT;i++)
176 {
177 issidrv[i].addr = addrs[i];
178 }
179
180 issi3733_led_t *cur = led_map;
181
182 while (cur < lede)
183 {
184 //BYTE: 1 + (SW-1)*16 + (CS-1)
185 cur->rgb.g = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swg-1)*16 + (cur->adr.cs-1));
186 cur->rgb.r = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swr-1)*16 + (cur->adr.cs-1));
187 cur->rgb.b = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swb-1)*16 + (cur->adr.cs-1));
188
189 //BYTE: 1 + (SW-1)*2 + (CS-1)/8
190 //BIT: (CS-1)%8
191 *(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swg-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
192 *(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swr-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
193 *(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swb-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
194
195 cur++;
196 }
197}
198
199void disp_calc_extents(void)
200{
201 issi3733_led_t *cur = led_map;
202
203 disp.left = 1e10;
204 disp.right = -1e10;
205 disp.top = -1e10;
206 disp.bottom = 1e10;
207
208 while (cur < lede)
209 {
210 if (cur->x < disp.left) disp.left = cur->x;
211 if (cur->x > disp.right) disp.right = cur->x;
212 if (cur->y < disp.bottom) disp.bottom = cur->y;
213 if (cur->y > disp.top) disp.top = cur->y;
214
215 cur++;
216 }
217
218 disp.width = disp.right - disp.left;
219 disp.height = disp.top - disp.bottom;
220}
221
222void disp_pixel_setup(void)
223{
224 issi3733_led_t *cur = led_map;
225
226 while (cur < lede)
227 {
228 cur->px = (cur->x - disp.left) / disp.width * 100;
229 cur->py = (cur->y - disp.top) / disp.height * 100;
230 *cur->rgb.r = 0;
231 *cur->rgb.g = 0;
232 *cur->rgb.b = 0;
233
234 cur++;
235 }
236}
237
238void led_matrix_prepare(void)
239{
240 disp_calc_extents();
241 disp_pixel_setup();
242}
243
244uint8_t led_enabled;
245float led_animation_speed;
246uint8_t led_animation_direction;
247uint8_t led_animation_breathing;
248uint8_t led_animation_breathe_cur;
249uint8_t breathe_step;
250uint8_t breathe_dir;
251uint64_t led_next_run;
252
253uint8_t led_animation_id;
254uint8_t led_lighting_mode;
255
256issi3733_led_t *led_cur;
257uint8_t led_per_run = 15;
258float breathe_mult;
259
260void led_matrix_run(led_setup_t *f)
261{
262 float ro;
263 float go;
264 float bo;
265 float px;
266 uint8_t led_this_run = 0;
267
268 if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
269 {
270 led_cur = led_map;
271
272 disp.frame += 1;
273
274 breathe_mult = 1;
275
276 if (led_animation_breathing)
277 {
278 led_animation_breathe_cur += breathe_step * breathe_dir;
279
280 if (led_animation_breathe_cur >= BREATHE_MAX_STEP)
281 breathe_dir = -1;
282 else if (led_animation_breathe_cur <= BREATHE_MIN_STEP)
283 breathe_dir = 1;
284
285 //Brightness curve created for 256 steps, 0 - ~98%
286 breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur;
287 if (breathe_mult > 1) breathe_mult = 1;
288 else if (breathe_mult < 0) breathe_mult = 0;
289 }
290 }
291
292 uint8_t fcur = 0;
293 uint8_t fmax = 0;
294
295 //Frames setup
296 while (f[fcur].end != 1)
297 {
298 fcur++; //Count frames
299 }
300
301 fmax = fcur; //Store total frames count
302
303 while (led_cur < lede && led_this_run < led_per_run)
304 {
305 ro = 0;
306 go = 0;
307 bo = 0;
308
309 if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255)
310 {
311 //Do not act on this LED
312 }
313 else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && led_cur->scan != 255)
314 {
315 //Do not act on this LED
316 }
317 else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY)
318 {
319 //Do not act on this LED (Only show indicators)
320 }
321 else
322 {
323 //Act on LED
324 for (fcur = 0; fcur < fmax; fcur++)
325 {
326 px = led_cur->px;
327 float pxmod;
328 pxmod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
329
330 //Add in any moving effects
331 if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
332 {
333 pxmod *= 100.0f;
334 pxmod = (uint32_t)pxmod % 10000;
335 pxmod /= 100.0f;
336
337 px -= pxmod;
338
339 if (px > 100) px -= 100;
340 else if (px < 0) px += 100;
341 }
342 else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
343 {
344 pxmod *= 100.0f;
345 pxmod = (uint32_t)pxmod % 10000;
346 pxmod /= 100.0f;
347 px += pxmod;
348
349 if (px > 100) px -= 100;
350 else if (px < 0) px += 100;
351 }
352
353 //Check if LED's px is in current frame
354 if (px < f[fcur].hs) continue;
355 if (px > f[fcur].he) continue;
356 //note: < 0 or > 100 continue
357
358 //Calculate the px within the start-stop percentage for color blending
359 px = (px - f[fcur].hs) / (f[fcur].he - f[fcur].hs);
360
361 //Add in any color effects
362 if (f[fcur].ef & EF_OVER)
363 {
364 ro = (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
365 go = (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
366 bo = (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
367 }
368 else if (f[fcur].ef & EF_SUBTRACT)
369 {
370 ro -= (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
371 go -= (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
372 bo -= (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
373 }
374 else
375 {
376 ro += (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
377 go += (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
378 bo += (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
379 }
380 }
381 }
382
383 //Clamp values 0-255
384 if (ro > 255) ro = 255; else if (ro < 0) ro = 0;
385 if (go > 255) go = 255; else if (go < 0) go = 0;
386 if (bo > 255) bo = 255; else if (bo < 0) bo = 0;
387
388 if (led_animation_breathing)
389 {
390 ro *= breathe_mult;
391 go *= breathe_mult;
392 bo *= breathe_mult;
393 }
394
395 *led_cur->rgb.r = (uint8_t)ro;
396 *led_cur->rgb.g = (uint8_t)go;
397 *led_cur->rgb.b = (uint8_t)bo;
398
399#ifdef USB_LED_INDICATOR_ENABLE
400 if (keyboard_leds())
401 {
402 uint8_t kbled = keyboard_leds();
403 if (
404 #if USB_LED_NUM_LOCK_SCANCODE != 255
405 (led_cur->scan == USB_LED_NUM_LOCK_SCANCODE && kbled & (1<<USB_LED_NUM_LOCK)) ||
406 #endif //NUM LOCK
407 #if USB_LED_CAPS_LOCK_SCANCODE != 255
408 (led_cur->scan == USB_LED_CAPS_LOCK_SCANCODE && kbled & (1<<USB_LED_CAPS_LOCK)) ||
409 #endif //CAPS LOCK
410 #if USB_LED_SCROLL_LOCK_SCANCODE != 255
411 (led_cur->scan == USB_LED_SCROLL_LOCK_SCANCODE && kbled & (1<<USB_LED_SCROLL_LOCK)) ||
412 #endif //SCROLL LOCK
413 #if USB_LED_COMPOSE_SCANCODE != 255
414 (led_cur->scan == USB_LED_COMPOSE_SCANCODE && kbled & (1<<USB_LED_COMPOSE)) ||
415 #endif //COMPOSE
416 #if USB_LED_KANA_SCANCODE != 255
417 (led_cur->scan == USB_LED_KANA_SCANCODE && kbled & (1<<USB_LED_KANA)) ||
418 #endif //KANA
419 (0))
420 {
421 if (*led_cur->rgb.r > 127) *led_cur->rgb.r = 0;
422 else *led_cur->rgb.r = 255;
423 if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0;
424 else *led_cur->rgb.g = 255;
425 if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0;
426 else *led_cur->rgb.b = 255;
427 }
428 }
429#endif //USB_LED_INDICATOR_ENABLE
430
431 led_cur++;
432 led_this_run++;
433 }
434}
435
436uint8_t led_matrix_init(void)
437{
438 DBGC(DC_LED_MATRIX_INIT_BEGIN);
439
440 issi3733_prepare_arrays();
441
442 led_matrix_prepare();
443
444 disp.frame = 0;
445 led_next_run = 0;
446
447 led_enabled = 1;
448 led_animation_id = 0;
449 led_lighting_mode = LED_MODE_NORMAL;
450 led_animation_speed = 4.0f;
451 led_animation_direction = 0;
452 led_animation_breathing = 0;
453 led_animation_breathe_cur = BREATHE_MIN_STEP;
454 breathe_step = 1;
455 breathe_dir = 1;
456
457 gcr_min_counter = 0;
458 v_5v_cat_hit = 0;
459
460 //Run led matrix code once for initial LED coloring
461 led_cur = 0;
462 led_matrix_run((led_setup_t*)led_setups[led_animation_id]);
463
464 DBGC(DC_LED_MATRIX_INIT_COMPLETE);
465
466 return 0;
467}
468
469#define LED_UPDATE_RATE 10 //ms
470
471//led data processing can take time, so process data in chunks to free up the processor
472//this is done through led_cur and lede
473void led_matrix_task(void)
474{
475 if (led_enabled)
476 {
477 //If an update may run and frame processing has completed
478 if (CLK_get_ms() >= led_next_run && led_cur == lede)
479 {
480 uint8_t drvid;
481
482 led_next_run = CLK_get_ms() + LED_UPDATE_RATE; //Set next frame update time
483
484 //NOTE: GCR does not need to be timed with LED processing, but there is really no harm
485 if (gcr_actual != gcr_actual_last)
486 {
487 for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
488 I2C_LED_Q_GCR(drvid); //Queue data
489 gcr_actual_last = gcr_actual;
490 }
491
492 for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
493 I2C_LED_Q_PWM(drvid); //Queue data
494
495 i2c_led_q_run();
496
497 led_cur = 0; //Signal next frame calculations may begin
498 }
499 }
500
501 //Process more data if not finished
502 if (led_cur != lede)
503 {
504 //m15_off; //debug profiling
505 led_matrix_run((led_setup_t*)led_setups[led_animation_id]);
506 //m15_on; //debug profiling
507 }
508}
509
diff --git a/tmk_core/protocol/arm_atsam/led_matrix.h b/tmk_core/protocol/arm_atsam/led_matrix.h
new file mode 100644
index 000000000..01b078b71
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/led_matrix.h
@@ -0,0 +1,142 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _LED_MATRIX_H_
19#define _LED_MATRIX_H_
20
21//From keyboard
22#include "config_led.h"
23
24//CS1-CS16 Current Source "Col"
25#define ISSI3733_CS_COUNT 16
26
27//SW1-SW12 Switch "Row"
28#define ISSI3733_SW_COUNT 12
29
30#define ISSI3733_LED_RGB_COUNT ISSI3733_CS_COUNT * ISSI3733_SW_COUNT
31#define ISSI3733_PG0_BYTES ISSI3733_LED_RGB_COUNT / 8 + 1 //+1 for first byte being memory start offset for I2C transfer
32#define ISSI3733_PG1_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
33#define ISSI3733_PG2_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
34#define ISSI3733_PG3_BYTES 18 + 1 //+1 for first byte being memory start offset for I2C transfer
35
36#define ISSI3733_PG_ONOFF_BYTES ISSI3733_PG0_BYTES
37#define ISSI3733_PG_OR_BYTES ISSI3733_PG0_BYTES
38#define ISSI3733_PG_SR_BYTES ISSI3733_PG0_BYTES
39#define ISSI3733_PG_PWM_BYTES ISSI3733_PG1_BYTES
40#define ISSI3733_PG_ABM_BYTES ISSI3733_PG2_BYTES
41#define ISSI3733_PG_FN_BYTES ISSI3733_PG3_BYTES
42
43typedef struct issi3733_driver_s {
44 uint8_t addr; //Address of the driver according to wiring "ISSI3733: Table 1 Slave Address"
45 uint8_t onoff[ISSI3733_PG_ONOFF_BYTES]; //PG0 - LED Control Register - LED On/Off Register
46 uint8_t open[ISSI3733_PG_OR_BYTES]; //PG0 - LED Control Register - LED Open Register
47 uint8_t shrt[ISSI3733_PG_SR_BYTES]; //PG0 - LED Control Register - LED Short Register
48 uint8_t pwm[ISSI3733_PG_PWM_BYTES]; //PG1 - PWM Register
49 uint8_t abm[ISSI3733_PG_ABM_BYTES]; //PG2 - Auto Breath Mode Register
50 uint8_t conf[ISSI3733_PG_FN_BYTES]; //PG3 - Function Register
51} issi3733_driver_t;
52
53typedef struct issi3733_rgb_s {
54 uint8_t *r; //Direct access into PWM data
55 uint8_t *g; //Direct access into PWM data
56 uint8_t *b; //Direct access into PWM data
57} issi3733_rgb_t;
58
59typedef struct issi3733_rgb_adr_s {
60 uint8_t drv; //Driver from given list
61 uint8_t cs; //CS
62 uint8_t swr; //SW Red
63 uint8_t swg; //SW Green
64 uint8_t swb; //SW Blue
65} issi3733_rgb_adr_t;
66
67typedef struct issi3733_led_s {
68 uint8_t id; //According to PCB ref
69 issi3733_rgb_t rgb; //PWM settings of R G B
70 issi3733_rgb_adr_t adr; //Hardware addresses
71 float x; //Physical position X
72 float y; //Physical position Y
73 float px; //Physical position X in percent
74 float py; //Physical position Y in percent
75 uint8_t scan; //Key scan code from wiring (set 0xFF if no key)
76} issi3733_led_t;
77
78typedef struct led_disp_s {
79 uint64_t frame;
80 float left;
81 float right;
82 float top;
83 float bottom;
84 float width;
85 float height;
86} led_disp_t;
87
88uint8_t led_matrix_init(void);
89
90#define LED_MODE_NORMAL 0 //Must be 0
91#define LED_MODE_KEYS_ONLY 1
92#define LED_MODE_NON_KEYS_ONLY 2
93#define LED_MODE_INDICATORS_ONLY 3
94#define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY //Must be highest value
95
96#define EF_NONE 0x00000000 //No effect
97#define EF_OVER 0x00000001 //Overwrite any previous color information with new
98#define EF_SCR_L 0x00000002 //Scroll left
99#define EF_SCR_R 0x00000004 //Scroll right
100#define EF_SUBTRACT 0x00000008 //Subtract color values
101
102typedef struct led_setup_s {
103 float hs; //Band begin at percent
104 float he; //Band end at percent
105 uint8_t rs; //Red start value
106 uint8_t re; //Red end value
107 uint8_t gs; //Green start value
108 uint8_t ge; //Green end value
109 uint8_t bs; //Blue start value
110 uint8_t be; //Blue end value
111 uint32_t ef; //Animation and color effects
112 uint8_t end; //Set to signal end of the setup
113} led_setup_t;
114
115extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
116
117extern uint8_t gcr_desired;
118extern uint8_t gcr_breathe;
119extern uint8_t gcr_actual;
120extern uint8_t gcr_actual_last;
121
122extern uint8_t led_animation_id;
123extern uint8_t led_enabled;
124extern float led_animation_speed;
125extern uint8_t led_lighting_mode;
126extern uint8_t led_animation_direction;
127extern uint8_t led_animation_breathing;
128extern uint8_t led_animation_breathe_cur;
129extern uint8_t breathe_dir;
130extern const uint8_t led_setups_count;
131
132extern void *led_setups[];
133
134extern issi3733_led_t *led_cur;
135extern issi3733_led_t *lede;
136
137void led_matrix_run(led_setup_t *f);
138void led_matrix_task(void);
139
140void gcr_compute(void);
141
142#endif //_LED_MATRIX_H_
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
new file mode 100644
index 000000000..e9514730e
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
@@ -0,0 +1,279 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "samd51j18a.h"
19#include "tmk_core/common/keyboard.h"
20
21#include "report.h"
22#include "host.h"
23#include "host_driver.h"
24#include "keycode_config.h"
25#include <string.h>
26#include "quantum.h"
27
28//From protocol directory
29#include "arm_atsam_protocol.h"
30
31//From keyboard's directory
32#include "config_led.h"
33
34uint8_t keyboard_leds(void);
35void send_keyboard(report_keyboard_t *report);
36void send_mouse(report_mouse_t *report);
37void send_system(uint16_t data);
38void send_consumer(uint16_t data);
39
40host_driver_t arm_atsam_driver = {
41 keyboard_leds,
42 send_keyboard,
43 send_mouse,
44 send_system,
45 send_consumer
46};
47
48uint8_t led_states;
49
50uint8_t keyboard_leds(void)
51{
52#ifdef NKRO_ENABLE
53 if (keymap_config.nkro)
54 return udi_hid_nkro_report_set;
55 else
56#endif //NKRO_ENABLE
57 return udi_hid_kbd_report_set;
58}
59
60void send_keyboard(report_keyboard_t *report)
61{
62 uint32_t irqflags;
63
64#ifdef NKRO_ENABLE
65 if (!keymap_config.nkro)
66 {
67#endif //NKRO_ENABLE
68 dprint("s-kbd\r\n");
69
70 irqflags = __get_PRIMASK();
71 __disable_irq();
72 __DMB();
73
74 memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE);
75 udi_hid_kbd_b_report_valid = 1;
76 udi_hid_kbd_send_report();
77
78 __DMB();
79 __set_PRIMASK(irqflags);
80#ifdef NKRO_ENABLE
81 }
82 else
83 {
84 dprint("s-nkro\r\n");
85
86 irqflags = __get_PRIMASK();
87 __disable_irq();
88 __DMB();
89
90 memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
91 udi_hid_nkro_b_report_valid = 1;
92 udi_hid_nkro_send_report();
93
94 __DMB();
95 __set_PRIMASK(irqflags);
96 }
97#endif //NKRO_ENABLE
98}
99
100void send_mouse(report_mouse_t *report)
101{
102#ifdef MOUSEKEY_ENABLE
103 uint32_t irqflags;
104
105 dprint("s-mou\r\n");
106
107 irqflags = __get_PRIMASK();
108 __disable_irq();
109 __DMB();
110
111 memcpy(udi_hid_mou_report, report, UDI_HID_MOU_REPORT_SIZE);
112 udi_hid_mou_b_report_valid = 1;
113 udi_hid_mou_send_report();
114
115 __DMB();
116 __set_PRIMASK(irqflags);
117#endif //MOUSEKEY_ENABLE
118}
119
120void send_system(uint16_t data)
121{
122#ifdef EXTRAKEY_ENABLE
123 dprintf("s-exks %i\r\n", data);
124
125 uint32_t irqflags;
126
127 irqflags = __get_PRIMASK();
128 __disable_irq();
129 __DMB();
130
131 udi_hid_exk_report.desc.report_id = REPORT_ID_SYSTEM;
132 if (data != 0) data = data - SYSTEM_POWER_DOWN + 1;
133 udi_hid_exk_report.desc.report_data = data;
134 udi_hid_exk_b_report_valid = 1;
135 udi_hid_exk_send_report();
136
137 __DMB();
138 __set_PRIMASK(irqflags);
139#endif //EXTRAKEY_ENABLE
140}
141
142void send_consumer(uint16_t data)
143{
144#ifdef EXTRAKEY_ENABLE
145 dprintf("s-exkc %i\r\n",data);
146
147 uint32_t irqflags;
148
149 irqflags = __get_PRIMASK();
150 __disable_irq();
151 __DMB();
152
153 udi_hid_exk_report.desc.report_id = REPORT_ID_CONSUMER;
154 udi_hid_exk_report.desc.report_data = data;
155 udi_hid_exk_b_report_valid = 1;
156 udi_hid_exk_send_report();
157
158 __DMB();
159 __set_PRIMASK(irqflags);
160#endif //EXTRAKEY_ENABLE
161}
162
163int main(void)
164{
165 led_ena;
166 m15_ena;
167
168 debug_code_init();
169
170 CLK_init();
171
172 ADC0_init();
173
174 SPI_Init();
175
176 i2c1_init();
177
178 matrix_init();
179
180 USB2422_init();
181
182 DBGC(DC_MAIN_UDC_START_BEGIN);
183 udc_start();
184 DBGC(DC_MAIN_UDC_START_COMPLETE);
185
186 DBGC(DC_MAIN_CDC_INIT_BEGIN);
187 CDC_init();
188 DBGC(DC_MAIN_CDC_INIT_COMPLETE);
189
190 while (USB2422_Port_Detect_Init() == 0) {}
191
192 led_off;
193 m15_off;
194
195 led_matrix_init();
196
197 while (I2C3733_Init_Control() != 1) {}
198 while (I2C3733_Init_Drivers() != 1) {}
199
200 I2C_DMAC_LED_Init();
201
202 i2c_led_q_init();
203
204 uint8_t drvid;
205 for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
206 I2C_LED_Q_ONOFF(drvid); //Queue data
207
208 keyboard_setup();
209
210 keyboard_init();
211
212 host_set_driver(&arm_atsam_driver);
213
214#ifdef VIRTSER_ENABLE
215 uint64_t next_print = 0;
216#endif //VIRTSER_ENABLE
217 uint64_t next_usb_checkup = 0;
218 uint64_t next_5v_checkup = 0;
219
220 v_5v_avg = adc_get(ADC_5V);
221
222 debug_code_disable();
223
224 while (1)
225 {
226 if (usb_state == USB_STATE_POWERDOWN)
227 {
228 led_on;
229 if (led_enabled)
230 {
231 for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
232 {
233 I2C3733_Control_Set(0);
234 }
235 }
236 while (usb_state == USB_STATE_POWERDOWN) {}
237 if (led_enabled)
238 {
239 for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
240 {
241 I2C3733_Control_Set(1);
242 }
243 }
244 led_off;
245 }
246
247 keyboard_task();
248
249 led_matrix_task();
250
251 if (CLK_get_ms() > next_5v_checkup)
252 {
253 next_5v_checkup = CLK_get_ms() + 5;
254
255 v_5v = adc_get(ADC_5V);
256 v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
257
258 gcr_compute();
259 }
260
261 if (CLK_get_ms() > next_usb_checkup)
262 {
263 next_usb_checkup = CLK_get_ms() + 10;
264
265 USB_HandleExtraDevice();
266 }
267
268#ifdef VIRTSER_ENABLE
269 if (CLK_get_ms() > next_print)
270 {
271 next_print = CLK_get_ms() + 250;
272 //dpf("5v=%i 5vu=%i dlow=%i dhi=%i gca=%i gcd=%i\r\n",v_5v,v_5v_avg,v_5v_avg-V5_LOW,v_5v_avg-V5_HIGH,gcr_actual,gcr_desired);
273 }
274#endif //VIRTSER_ENABLE
275 }
276
277 return 1;
278}
279
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.h b/tmk_core/protocol/arm_atsam/main_arm_atsam.h
new file mode 100644
index 000000000..78205e2e1
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.h
@@ -0,0 +1,23 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _MAIN_ARM_ATSAM_H_
19#define _MAIN_ARM_ATSAM_H_
20
21uint8_t keyboard_leds(void);
22
23#endif //_MAIN_ARM_ATSAM_H_
diff --git a/tmk_core/protocol/arm_atsam/md_bootloader.h b/tmk_core/protocol/arm_atsam/md_bootloader.h
new file mode 100644
index 000000000..1316876c8
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/md_bootloader.h
@@ -0,0 +1,18 @@
1#ifndef _MD_BOOTLOADER_H_
2#define _MD_BOOTLOADER_H_
3
4extern uint32_t _srom;
5extern uint32_t _lrom;
6extern uint32_t _erom;
7
8#define BOOTLOADER_SERIAL_MAX_SIZE 20 //DO NOT MODIFY!
9
10#ifdef MD_BOOTLOADER
11
12#define MCU_HZ 48000000
13#define I2C_HZ 0 //Not used
14
15#endif //MD_BOOTLOADER
16
17#endif //_MD_BOOTLOADER_H_
18
diff --git a/tmk_core/protocol/arm_atsam/spi.c b/tmk_core/protocol/arm_atsam/spi.c
new file mode 100644
index 000000000..6036a9220
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi.c
@@ -0,0 +1,90 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20Srdata_t srdata;
21
22void SPI_WriteSRData(void)
23{
24 uint16_t timeout;
25
26 SC2_RCLCK_LO;
27
28 timeout = 50000;
29 while (!(SCSPI->SPI.INTFLAG.bit.DRE) && --timeout) { DBGC(DC_SPI_WRITE_DRE); }
30
31 SCSPI->SPI.DATA.bit.DATA = srdata.reg & 0xFF; //Shift in bits 7-0
32 timeout = 50000;
33 while (!(SCSPI->SPI.INTFLAG.bit.TXC) && --timeout) { DBGC(DC_SPI_WRITE_TXC_1); }
34
35 SCSPI->SPI.DATA.bit.DATA = (srdata.reg >> 8) & 0xFF; //Shift in bits 15-8
36 timeout = 50000;
37 while (!(SCSPI->SPI.INTFLAG.bit.TXC) && --timeout) { DBGC(DC_SPI_WRITE_TXC_2); }
38
39 SC2_RCLCK_HI;
40}
41
42void SPI_Init(void)
43{
44 uint32_t timeout;
45
46 DBGC(DC_SPI_INIT_BEGIN);
47
48 CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
49
50 PORT->Group[0].PMUX[6].bit.PMUXE = 2;
51 PORT->Group[0].PMUX[6].bit.PMUXO = 2;
52 PORT->Group[0].PINCFG[12].bit.PMUXEN = 1;
53 PORT->Group[0].PINCFG[13].bit.PMUXEN = 1;
54
55 //Configure Shift Registers
56 SC2_DIRSET;
57 SC2_RCLCK_HI;
58 SC2_OE_DIS;
59
60 SCSPI->SPI.CTRLA.bit.DORD = 1;
61 SCSPI->SPI.CTRLA.bit.CPOL = 1;
62 SCSPI->SPI.CTRLA.bit.CPHA = 1;
63 SCSPI->SPI.CTRLA.bit.DIPO = 3;
64 SCSPI->SPI.CTRLA.bit.MODE = 3; //master
65
66 SCSPI->SPI.CTRLA.bit.ENABLE = 1;
67 timeout = 50000;
68 while (SCSPI->SPI.SYNCBUSY.bit.ENABLE && timeout--) { DBGC(DC_SPI_SYNC_ENABLING); }
69
70 srdata.reg = 0;
71 srdata.bit.HUB_CONNECT = 0;
72 srdata.bit.HUB_RESET_N = 0;
73 srdata.bit.S_UP = 0;
74 srdata.bit.E_UP_N = 1;
75 srdata.bit.S_DN1 = 1;
76 srdata.bit.E_DN1_N = 1;
77 srdata.bit.E_VBUS_1 = 0;
78 srdata.bit.E_VBUS_2 = 0;
79 srdata.bit.SRC_1 = 1;
80 srdata.bit.SRC_2 = 1;
81 srdata.bit.IRST = 1;
82 srdata.bit.SDB_N = 0;
83 SPI_WriteSRData();
84
85 //Enable register output
86 SC2_OE_ENA;
87
88 DBGC(DC_SPI_INIT_COMPLETE);
89}
90
diff --git a/tmk_core/protocol/arm_atsam/spi.h b/tmk_core/protocol/arm_atsam/spi.h
new file mode 100644
index 000000000..3412dfc36
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi.h
@@ -0,0 +1,63 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _SPI_H_
19#define _SPI_H_
20
21//TODO: PS: Should bring ports to keyboard configuration
22
23#define SCSPI SERCOM2
24
25#define P14_DIR 0x00004000 /* PIN14 DIR Bit */
26#define P14_OUT 0x00004000 /* PIN14 OUT Bit */
27#define P15_DIR 0x00008000 /* PIN15 DIR Bit */
28#define P15_OUT 0x00008000 /* PIN15 OUT Bit */
29
30#define SC2_RCLCK_LO REG_PORT_OUTCLR1 = P14_OUT /* PB14 Low, SC2_RCLCK Low */
31#define SC2_RCLCK_HI REG_PORT_OUTSET1 = P14_OUT /* PB14 High, SC2_RCLCK High */
32#define SC2_OE_ENA REG_PORT_OUTCLR1 = P15_OUT /* PB15 Low, SC2_OE_N Low (Shift register enabled) */
33#define SC2_OE_DIS REG_PORT_OUTSET1 = P15_OUT /* PB15 High, SC2_OE_N High (Shift register disabled) */
34#define SC2_DIRSET REG_PORT_DIRSET1 = P14_DIR | P15_DIR; /* PB14 PB15 OUT */
35
36typedef union {
37 struct {
38 uint16_t RSVD4:1; /*!< bit: 0 */
39 uint16_t RSVD3:1; /*!< bit: 1 */
40 uint16_t RSVD2:1; /*!< bit: 2 */
41 uint16_t RSVD1:1; /*!< bit: 3 */
42 uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN THE CHIP WHEN 0, RUN WHEN 1 */
43 uint16_t IRST:1; /*!< bit: 5 RESET THE IS3733 I2C WHEN 1, RUN WHEN 0 */
44 uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
45 uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
46 uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
47 uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
48 uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
49 uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
50 uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
51 uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
52 uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
53 uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
54 } bit; /*!< Structure used for bit access */
55 uint16_t reg; /*!< Type used for register access */
56} Srdata_t;
57
58extern Srdata_t srdata;
59
60void SPI_WriteSRData(void);
61void SPI_Init(void);
62
63#endif //_SPI_H_
diff --git a/tmk_core/protocol/arm_atsam/startup.c b/tmk_core/protocol/arm_atsam/startup.c
new file mode 100644
index 000000000..a62d02f1c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/startup.c
@@ -0,0 +1,548 @@
1/**
2 * \file
3 *
4 * \brief gcc starttup file for SAMD51
5 *
6 * Copyright (c) 2017 Microchip Technology Inc.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License"); you may
15 * not use this file except in compliance with the License.
16 * You may obtain a copy of the Licence at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
22 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *
26 * \asf_license_stop
27 *
28 */
29
30#include "samd51.h"
31
32/* Initialize segments */
33extern uint32_t _sfixed;
34extern uint32_t _efixed;
35extern uint32_t _etext;
36extern uint32_t _srelocate;
37extern uint32_t _erelocate;
38extern uint32_t _szero;
39extern uint32_t _ezero;
40extern uint32_t _sstack;
41extern uint32_t _estack;
42
43/** \cond DOXYGEN_SHOULD_SKIP_THIS */
44int main(void);
45/** \endcond */
46
47void __libc_init_array(void);
48
49/* Default empty handler */
50void Dummy_Handler(void);
51
52/* Cortex-M4 core handlers */
53void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
54void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
55void MemManage_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
56void BusFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
57void UsageFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
58void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
59void DebugMon_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
60void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
61void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
62
63/* Peripherals handlers */
64void PM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
65void MCLK_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
66void OSCCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
67void OSCCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
68void OSCCTRL_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
69void OSCCTRL_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
70void OSCCTRL_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
71void OSC32KCTRL_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
72void SUPC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
73void SUPC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_BOD12DET, SUPC_BOD33DET */
74void WDT_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
75void RTC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
76void EIC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_0 */
77void EIC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_1 */
78void EIC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_2 */
79void EIC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_3 */
80void EIC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_4 */
81void EIC_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_5 */
82void EIC_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_6 */
83void EIC_7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_7 */
84void EIC_8_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_8 */
85void EIC_9_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_9 */
86void EIC_10_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_10 */
87void EIC_11_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_11 */
88void EIC_12_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_12 */
89void EIC_13_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_13 */
90void EIC_14_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_14 */
91void EIC_15_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_15 */
92void FREQM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
93void NVMCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
94void NVMCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
95void DMAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
96void DMAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
97void DMAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
98void DMAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
99void DMAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
100void EVSYS_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_0, EVSYS_OVR_0 */
101void EVSYS_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_1, EVSYS_OVR_1 */
102void EVSYS_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_2, EVSYS_OVR_2 */
103void EVSYS_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_3, EVSYS_OVR_3 */
104void EVSYS_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
105void PAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
106void TAL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_BRK */
107void TAL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_IPS_0, TAL_IPS_1 */
108void RAMECC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
109void SERCOM0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_0 */
110void SERCOM0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_1 */
111void SERCOM0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_2 */
112void SERCOM0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
113void SERCOM1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_0 */
114void SERCOM1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_1 */
115void SERCOM1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_2 */
116void SERCOM1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
117void SERCOM2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_0 */
118void SERCOM2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_1 */
119void SERCOM2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_2 */
120void SERCOM2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
121void SERCOM3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_0 */
122void SERCOM3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_1 */
123void SERCOM3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_2 */
124void SERCOM3_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
125#ifdef ID_SERCOM4
126void SERCOM4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_0 */
127void SERCOM4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_1 */
128void SERCOM4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_2 */
129void SERCOM4_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
130#endif
131#ifdef ID_SERCOM5
132void SERCOM5_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_0 */
133void SERCOM5_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_1 */
134void SERCOM5_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_2 */
135void SERCOM5_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
136#endif
137#ifdef ID_SERCOM6
138void SERCOM6_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_0 */
139void SERCOM6_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_1 */
140void SERCOM6_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_2 */
141void SERCOM6_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
142#endif
143#ifdef ID_SERCOM7
144void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_0 */
145void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_1 */
146void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_2 */
147void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
148#endif
149#ifdef ID_CAN0
150void CAN0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
151#endif
152#ifdef ID_CAN1
153void CAN1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
154#endif
155#ifdef ID_USB
156void USB_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
157void USB_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_SOF_HSOF */
158void USB_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
159void USB_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
160#endif
161#ifdef ID_GMAC
162void GMAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
163#endif
164void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
165void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_0 */
166void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_1 */
167void TCC0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_2 */
168void TCC0_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_3 */
169void TCC0_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_4 */
170void TCC0_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_5 */
171void TCC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
172void TCC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_0 */
173void TCC1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_1 */
174void TCC1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_2 */
175void TCC1_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_3 */
176void TCC2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
177void TCC2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_0 */
178void TCC2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_1 */
179void TCC2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_2 */
180#ifdef ID_TCC3
181void TCC3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
182void TCC3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_0 */
183void TCC3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_1 */
184#endif
185#ifdef ID_TCC4
186void TCC4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
187void TCC4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_0 */
188void TCC4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_1 */
189#endif
190void TC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
191void TC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
192void TC2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
193void TC3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
194#ifdef ID_TC4
195void TC4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
196#endif
197#ifdef ID_TC5
198void TC5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
199#endif
200#ifdef ID_TC6
201void TC6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
202#endif
203#ifdef ID_TC7
204void TC7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
205#endif
206void PDEC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
207void PDEC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_0 */
208void PDEC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_1 */
209void ADC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_OVERRUN, ADC0_WINMON */
210void ADC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_RESRDY */
211void ADC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_OVERRUN, ADC1_WINMON */
212void ADC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_RESRDY */
213void AC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
214void DAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
215void DAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_0 */
216void DAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_1 */
217void DAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_0 */
218void DAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_1 */
219#ifdef ID_I2S
220void I2S_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
221#endif
222void PCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
223void AES_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
224void TRNG_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
225#ifdef ID_ICM
226void ICM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
227#endif
228#ifdef ID_PUKCC
229void PUKCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
230#endif
231void QSPI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
232#ifdef ID_SDHC0
233void SDHC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
234#endif
235#ifdef ID_SDHC1
236void SDHC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
237#endif
238
239/* Exception Table */
240__attribute__ ((section(".vectors")))
241const DeviceVectors exception_table = {
242
243 /* Configure Initial Stack Pointer, using linker-generated symbols */
244 .pvStack = (void*) (&_estack),
245
246 .pfnReset_Handler = (void*) Reset_Handler,
247 .pfnNMI_Handler = (void*) NMI_Handler,
248 .pfnHardFault_Handler = (void*) HardFault_Handler,
249 .pfnMemManage_Handler = (void*) MemManage_Handler,
250 .pfnBusFault_Handler = (void*) BusFault_Handler,
251 .pfnUsageFault_Handler = (void*) UsageFault_Handler,
252 .pvReservedM9 = (void*) (0UL), /* Reserved */
253 .pvReservedM8 = (void*) (0UL), /* Reserved */
254 .pvReservedM7 = (void*) (0UL), /* Reserved */
255 .pvReservedM6 = (void*) (0UL), /* Reserved */
256 .pfnSVC_Handler = (void*) SVC_Handler,
257 .pfnDebugMon_Handler = (void*) DebugMon_Handler,
258 .pvReservedM3 = (void*) (0UL), /* Reserved */
259 .pfnPendSV_Handler = (void*) PendSV_Handler,
260 .pfnSysTick_Handler = (void*) SysTick_Handler,
261
262 /* Configurable interrupts */
263 .pfnPM_Handler = (void*) PM_Handler, /* 0 Power Manager */
264 .pfnMCLK_Handler = (void*) MCLK_Handler, /* 1 Main Clock */
265 .pfnOSCCTRL_0_Handler = (void*) OSCCTRL_0_Handler, /* 2 OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
266 .pfnOSCCTRL_1_Handler = (void*) OSCCTRL_1_Handler, /* 3 OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
267 .pfnOSCCTRL_2_Handler = (void*) OSCCTRL_2_Handler, /* 4 OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
268 .pfnOSCCTRL_3_Handler = (void*) OSCCTRL_3_Handler, /* 5 OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
269 .pfnOSCCTRL_4_Handler = (void*) OSCCTRL_4_Handler, /* 6 OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
270 .pfnOSC32KCTRL_Handler = (void*) OSC32KCTRL_Handler, /* 7 32kHz Oscillators Control */
271 .pfnSUPC_0_Handler = (void*) SUPC_0_Handler, /* 8 SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
272 .pfnSUPC_1_Handler = (void*) SUPC_1_Handler, /* 9 SUPC_BOD12DET, SUPC_BOD33DET */
273 .pfnWDT_Handler = (void*) WDT_Handler, /* 10 Watchdog Timer */
274 .pfnRTC_Handler = (void*) RTC_Handler, /* 11 Real-Time Counter */
275 .pfnEIC_0_Handler = (void*) EIC_0_Handler, /* 12 EIC_EXTINT_0 */
276 .pfnEIC_1_Handler = (void*) EIC_1_Handler, /* 13 EIC_EXTINT_1 */
277 .pfnEIC_2_Handler = (void*) EIC_2_Handler, /* 14 EIC_EXTINT_2 */
278 .pfnEIC_3_Handler = (void*) EIC_3_Handler, /* 15 EIC_EXTINT_3 */
279 .pfnEIC_4_Handler = (void*) EIC_4_Handler, /* 16 EIC_EXTINT_4 */
280 .pfnEIC_5_Handler = (void*) EIC_5_Handler, /* 17 EIC_EXTINT_5 */
281 .pfnEIC_6_Handler = (void*) EIC_6_Handler, /* 18 EIC_EXTINT_6 */
282 .pfnEIC_7_Handler = (void*) EIC_7_Handler, /* 19 EIC_EXTINT_7 */
283 .pfnEIC_8_Handler = (void*) EIC_8_Handler, /* 20 EIC_EXTINT_8 */
284 .pfnEIC_9_Handler = (void*) EIC_9_Handler, /* 21 EIC_EXTINT_9 */
285 .pfnEIC_10_Handler = (void*) EIC_10_Handler, /* 22 EIC_EXTINT_10 */
286 .pfnEIC_11_Handler = (void*) EIC_11_Handler, /* 23 EIC_EXTINT_11 */
287 .pfnEIC_12_Handler = (void*) EIC_12_Handler, /* 24 EIC_EXTINT_12 */
288 .pfnEIC_13_Handler = (void*) EIC_13_Handler, /* 25 EIC_EXTINT_13 */
289 .pfnEIC_14_Handler = (void*) EIC_14_Handler, /* 26 EIC_EXTINT_14 */
290 .pfnEIC_15_Handler = (void*) EIC_15_Handler, /* 27 EIC_EXTINT_15 */
291 .pfnFREQM_Handler = (void*) FREQM_Handler, /* 28 Frequency Meter */
292 .pfnNVMCTRL_0_Handler = (void*) NVMCTRL_0_Handler, /* 29 NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
293 .pfnNVMCTRL_1_Handler = (void*) NVMCTRL_1_Handler, /* 30 NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
294 .pfnDMAC_0_Handler = (void*) DMAC_0_Handler, /* 31 DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
295 .pfnDMAC_1_Handler = (void*) DMAC_1_Handler, /* 32 DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
296 .pfnDMAC_2_Handler = (void*) DMAC_2_Handler, /* 33 DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
297 .pfnDMAC_3_Handler = (void*) DMAC_3_Handler, /* 34 DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
298 .pfnDMAC_4_Handler = (void*) DMAC_4_Handler, /* 35 DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
299 .pfnEVSYS_0_Handler = (void*) EVSYS_0_Handler, /* 36 EVSYS_EVD_0, EVSYS_OVR_0 */
300 .pfnEVSYS_1_Handler = (void*) EVSYS_1_Handler, /* 37 EVSYS_EVD_1, EVSYS_OVR_1 */
301 .pfnEVSYS_2_Handler = (void*) EVSYS_2_Handler, /* 38 EVSYS_EVD_2, EVSYS_OVR_2 */
302 .pfnEVSYS_3_Handler = (void*) EVSYS_3_Handler, /* 39 EVSYS_EVD_3, EVSYS_OVR_3 */
303 .pfnEVSYS_4_Handler = (void*) EVSYS_4_Handler, /* 40 EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
304 .pfnPAC_Handler = (void*) PAC_Handler, /* 41 Peripheral Access Controller */
305 .pfnTAL_0_Handler = (void*) TAL_0_Handler, /* 42 TAL_BRK */
306 .pfnTAL_1_Handler = (void*) TAL_1_Handler, /* 43 TAL_IPS_0, TAL_IPS_1 */
307 .pvReserved44 = (void*) (0UL), /* 44 Reserved */
308 .pfnRAMECC_Handler = (void*) RAMECC_Handler, /* 45 RAM ECC */
309 .pfnSERCOM0_0_Handler = (void*) SERCOM0_0_Handler, /* 46 SERCOM0_0 */
310 .pfnSERCOM0_1_Handler = (void*) SERCOM0_1_Handler, /* 47 SERCOM0_1 */
311 .pfnSERCOM0_2_Handler = (void*) SERCOM0_2_Handler, /* 48 SERCOM0_2 */
312 .pfnSERCOM0_3_Handler = (void*) SERCOM0_3_Handler, /* 49 SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
313 .pfnSERCOM1_0_Handler = (void*) SERCOM1_0_Handler, /* 50 SERCOM1_0 */
314 .pfnSERCOM1_1_Handler = (void*) SERCOM1_1_Handler, /* 51 SERCOM1_1 */
315 .pfnSERCOM1_2_Handler = (void*) SERCOM1_2_Handler, /* 52 SERCOM1_2 */
316 .pfnSERCOM1_3_Handler = (void*) SERCOM1_3_Handler, /* 53 SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
317 .pfnSERCOM2_0_Handler = (void*) SERCOM2_0_Handler, /* 54 SERCOM2_0 */
318 .pfnSERCOM2_1_Handler = (void*) SERCOM2_1_Handler, /* 55 SERCOM2_1 */
319 .pfnSERCOM2_2_Handler = (void*) SERCOM2_2_Handler, /* 56 SERCOM2_2 */
320 .pfnSERCOM2_3_Handler = (void*) SERCOM2_3_Handler, /* 57 SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
321 .pfnSERCOM3_0_Handler = (void*) SERCOM3_0_Handler, /* 58 SERCOM3_0 */
322 .pfnSERCOM3_1_Handler = (void*) SERCOM3_1_Handler, /* 59 SERCOM3_1 */
323 .pfnSERCOM3_2_Handler = (void*) SERCOM3_2_Handler, /* 60 SERCOM3_2 */
324 .pfnSERCOM3_3_Handler = (void*) SERCOM3_3_Handler, /* 61 SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
325#ifdef ID_SERCOM4
326 .pfnSERCOM4_0_Handler = (void*) SERCOM4_0_Handler, /* 62 SERCOM4_0 */
327 .pfnSERCOM4_1_Handler = (void*) SERCOM4_1_Handler, /* 63 SERCOM4_1 */
328 .pfnSERCOM4_2_Handler = (void*) SERCOM4_2_Handler, /* 64 SERCOM4_2 */
329 .pfnSERCOM4_3_Handler = (void*) SERCOM4_3_Handler, /* 65 SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
330#else
331 .pvReserved62 = (void*) (0UL), /* 62 Reserved */
332 .pvReserved63 = (void*) (0UL), /* 63 Reserved */
333 .pvReserved64 = (void*) (0UL), /* 64 Reserved */
334 .pvReserved65 = (void*) (0UL), /* 65 Reserved */
335#endif
336#ifdef ID_SERCOM5
337 .pfnSERCOM5_0_Handler = (void*) SERCOM5_0_Handler, /* 66 SERCOM5_0 */
338 .pfnSERCOM5_1_Handler = (void*) SERCOM5_1_Handler, /* 67 SERCOM5_1 */
339 .pfnSERCOM5_2_Handler = (void*) SERCOM5_2_Handler, /* 68 SERCOM5_2 */
340 .pfnSERCOM5_3_Handler = (void*) SERCOM5_3_Handler, /* 69 SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
341#else
342 .pvReserved66 = (void*) (0UL), /* 66 Reserved */
343 .pvReserved67 = (void*) (0UL), /* 67 Reserved */
344 .pvReserved68 = (void*) (0UL), /* 68 Reserved */
345 .pvReserved69 = (void*) (0UL), /* 69 Reserved */
346#endif
347#ifdef ID_SERCOM6
348 .pfnSERCOM6_0_Handler = (void*) SERCOM6_0_Handler, /* 70 SERCOM6_0 */
349 .pfnSERCOM6_1_Handler = (void*) SERCOM6_1_Handler, /* 71 SERCOM6_1 */
350 .pfnSERCOM6_2_Handler = (void*) SERCOM6_2_Handler, /* 72 SERCOM6_2 */
351 .pfnSERCOM6_3_Handler = (void*) SERCOM6_3_Handler, /* 73 SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
352#else
353 .pvReserved70 = (void*) (0UL), /* 70 Reserved */
354 .pvReserved71 = (void*) (0UL), /* 71 Reserved */
355 .pvReserved72 = (void*) (0UL), /* 72 Reserved */
356 .pvReserved73 = (void*) (0UL), /* 73 Reserved */
357#endif
358#ifdef ID_SERCOM7
359 .pfnSERCOM7_0_Handler = (void*) SERCOM7_0_Handler, /* 74 SERCOM7_0 */
360 .pfnSERCOM7_1_Handler = (void*) SERCOM7_1_Handler, /* 75 SERCOM7_1 */
361 .pfnSERCOM7_2_Handler = (void*) SERCOM7_2_Handler, /* 76 SERCOM7_2 */
362 .pfnSERCOM7_3_Handler = (void*) SERCOM7_3_Handler, /* 77 SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
363#else
364 .pvReserved74 = (void*) (0UL), /* 74 Reserved */
365 .pvReserved75 = (void*) (0UL), /* 75 Reserved */
366 .pvReserved76 = (void*) (0UL), /* 76 Reserved */
367 .pvReserved77 = (void*) (0UL), /* 77 Reserved */
368#endif
369#ifdef ID_CAN0
370 .pfnCAN0_Handler = (void*) CAN0_Handler, /* 78 Control Area Network 0 */
371#else
372 .pvReserved78 = (void*) (0UL), /* 78 Reserved */
373#endif
374#ifdef ID_CAN1
375 .pfnCAN1_Handler = (void*) CAN1_Handler, /* 79 Control Area Network 1 */
376#else
377 .pvReserved79 = (void*) (0UL), /* 79 Reserved */
378#endif
379#ifdef ID_USB
380 .pfnUSB_0_Handler = (void*) USB_0_Handler, /* 80 USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
381 .pfnUSB_1_Handler = (void*) USB_1_Handler, /* 81 USB_SOF_HSOF */
382 .pfnUSB_2_Handler = (void*) USB_2_Handler, /* 82 USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
383 .pfnUSB_3_Handler = (void*) USB_3_Handler, /* 83 USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
384#else
385 .pvReserved80 = (void*) (0UL), /* 80 Reserved */
386 .pvReserved81 = (void*) (0UL), /* 81 Reserved */
387 .pvReserved82 = (void*) (0UL), /* 82 Reserved */
388 .pvReserved83 = (void*) (0UL), /* 83 Reserved */
389#endif
390#ifdef ID_GMAC
391 .pfnGMAC_Handler = (void*) GMAC_Handler, /* 84 Ethernet MAC */
392#else
393 .pvReserved84 = (void*) (0UL), /* 84 Reserved */
394#endif
395 .pfnTCC0_0_Handler = (void*) TCC0_0_Handler, /* 85 TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
396 .pfnTCC0_1_Handler = (void*) TCC0_1_Handler, /* 86 TCC0_MC_0 */
397 .pfnTCC0_2_Handler = (void*) TCC0_2_Handler, /* 87 TCC0_MC_1 */
398 .pfnTCC0_3_Handler = (void*) TCC0_3_Handler, /* 88 TCC0_MC_2 */
399 .pfnTCC0_4_Handler = (void*) TCC0_4_Handler, /* 89 TCC0_MC_3 */
400 .pfnTCC0_5_Handler = (void*) TCC0_5_Handler, /* 90 TCC0_MC_4 */
401 .pfnTCC0_6_Handler = (void*) TCC0_6_Handler, /* 91 TCC0_MC_5 */
402 .pfnTCC1_0_Handler = (void*) TCC1_0_Handler, /* 92 TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
403 .pfnTCC1_1_Handler = (void*) TCC1_1_Handler, /* 93 TCC1_MC_0 */
404 .pfnTCC1_2_Handler = (void*) TCC1_2_Handler, /* 94 TCC1_MC_1 */
405 .pfnTCC1_3_Handler = (void*) TCC1_3_Handler, /* 95 TCC1_MC_2 */
406 .pfnTCC1_4_Handler = (void*) TCC1_4_Handler, /* 96 TCC1_MC_3 */
407 .pfnTCC2_0_Handler = (void*) TCC2_0_Handler, /* 97 TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
408 .pfnTCC2_1_Handler = (void*) TCC2_1_Handler, /* 98 TCC2_MC_0 */
409 .pfnTCC2_2_Handler = (void*) TCC2_2_Handler, /* 99 TCC2_MC_1 */
410 .pfnTCC2_3_Handler = (void*) TCC2_3_Handler, /* 100 TCC2_MC_2 */
411#ifdef ID_TCC3
412 .pfnTCC3_0_Handler = (void*) TCC3_0_Handler, /* 101 TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
413 .pfnTCC3_1_Handler = (void*) TCC3_1_Handler, /* 102 TCC3_MC_0 */
414 .pfnTCC3_2_Handler = (void*) TCC3_2_Handler, /* 103 TCC3_MC_1 */
415#else
416 .pvReserved101 = (void*) (0UL), /* 101 Reserved */
417 .pvReserved102 = (void*) (0UL), /* 102 Reserved */
418 .pvReserved103 = (void*) (0UL), /* 103 Reserved */
419#endif
420#ifdef ID_TCC4
421 .pfnTCC4_0_Handler = (void*) TCC4_0_Handler, /* 104 TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
422 .pfnTCC4_1_Handler = (void*) TCC4_1_Handler, /* 105 TCC4_MC_0 */
423 .pfnTCC4_2_Handler = (void*) TCC4_2_Handler, /* 106 TCC4_MC_1 */
424#else
425 .pvReserved104 = (void*) (0UL), /* 104 Reserved */
426 .pvReserved105 = (void*) (0UL), /* 105 Reserved */
427 .pvReserved106 = (void*) (0UL), /* 106 Reserved */
428#endif
429 .pfnTC0_Handler = (void*) TC0_Handler, /* 107 Basic Timer Counter 0 */
430 .pfnTC1_Handler = (void*) TC1_Handler, /* 108 Basic Timer Counter 1 */
431 .pfnTC2_Handler = (void*) TC2_Handler, /* 109 Basic Timer Counter 2 */
432 .pfnTC3_Handler = (void*) TC3_Handler, /* 110 Basic Timer Counter 3 */
433#ifdef ID_TC4
434 .pfnTC4_Handler = (void*) TC4_Handler, /* 111 Basic Timer Counter 4 */
435#else
436 .pvReserved111 = (void*) (0UL), /* 111 Reserved */
437#endif
438#ifdef ID_TC5
439 .pfnTC5_Handler = (void*) TC5_Handler, /* 112 Basic Timer Counter 5 */
440#else
441 .pvReserved112 = (void*) (0UL), /* 112 Reserved */
442#endif
443#ifdef ID_TC6
444 .pfnTC6_Handler = (void*) TC6_Handler, /* 113 Basic Timer Counter 6 */
445#else
446 .pvReserved113 = (void*) (0UL), /* 113 Reserved */
447#endif
448#ifdef ID_TC7
449 .pfnTC7_Handler = (void*) TC7_Handler, /* 114 Basic Timer Counter 7 */
450#else
451 .pvReserved114 = (void*) (0UL), /* 114 Reserved */
452#endif
453 .pfnPDEC_0_Handler = (void*) PDEC_0_Handler, /* 115 PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
454 .pfnPDEC_1_Handler = (void*) PDEC_1_Handler, /* 116 PDEC_MC_0 */
455 .pfnPDEC_2_Handler = (void*) PDEC_2_Handler, /* 117 PDEC_MC_1 */
456 .pfnADC0_0_Handler = (void*) ADC0_0_Handler, /* 118 ADC0_OVERRUN, ADC0_WINMON */
457 .pfnADC0_1_Handler = (void*) ADC0_1_Handler, /* 119 ADC0_RESRDY */
458 .pfnADC1_0_Handler = (void*) ADC1_0_Handler, /* 120 ADC1_OVERRUN, ADC1_WINMON */
459 .pfnADC1_1_Handler = (void*) ADC1_1_Handler, /* 121 ADC1_RESRDY */
460 .pfnAC_Handler = (void*) AC_Handler, /* 122 Analog Comparators */
461 .pfnDAC_0_Handler = (void*) DAC_0_Handler, /* 123 DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
462 .pfnDAC_1_Handler = (void*) DAC_1_Handler, /* 124 DAC_EMPTY_0 */
463 .pfnDAC_2_Handler = (void*) DAC_2_Handler, /* 125 DAC_EMPTY_1 */
464 .pfnDAC_3_Handler = (void*) DAC_3_Handler, /* 126 DAC_RESRDY_0 */
465 .pfnDAC_4_Handler = (void*) DAC_4_Handler, /* 127 DAC_RESRDY_1 */
466#ifdef ID_I2S
467 .pfnI2S_Handler = (void*) I2S_Handler, /* 128 Inter-IC Sound Interface */
468#else
469 .pvReserved128 = (void*) (0UL), /* 128 Reserved */
470#endif
471 .pfnPCC_Handler = (void*) PCC_Handler, /* 129 Parallel Capture Controller */
472 .pfnAES_Handler = (void*) AES_Handler, /* 130 Advanced Encryption Standard */
473 .pfnTRNG_Handler = (void*) TRNG_Handler, /* 131 True Random Generator */
474#ifdef ID_ICM
475 .pfnICM_Handler = (void*) ICM_Handler, /* 132 Integrity Check Monitor */
476#else
477 .pvReserved132 = (void*) (0UL), /* 132 Reserved */
478#endif
479#ifdef ID_PUKCC
480 .pfnPUKCC_Handler = (void*) PUKCC_Handler, /* 133 PUblic-Key Cryptography Controller */
481#else
482 .pvReserved133 = (void*) (0UL), /* 133 Reserved */
483#endif
484 .pfnQSPI_Handler = (void*) QSPI_Handler, /* 134 Quad SPI interface */
485#ifdef ID_SDHC0
486 .pfnSDHC0_Handler = (void*) SDHC0_Handler, /* 135 SD/MMC Host Controller 0 */
487#else
488 .pvReserved135 = (void*) (0UL), /* 135 Reserved */
489#endif
490#ifdef ID_SDHC1
491 .pfnSDHC1_Handler = (void*) SDHC1_Handler /* 136 SD/MMC Host Controller 1 */
492#else
493 .pvReserved136 = (void*) (0UL) /* 136 Reserved */
494#endif
495};
496
497/**
498 * \brief This is the code that gets called on processor reset.
499 * To initialize the device, and call the main() routine.
500 */
501void Reset_Handler(void)
502{
503 uint32_t *pSrc, *pDest;
504
505 /* Initialize the relocate segment */
506 pSrc = &_etext;
507 pDest = &_srelocate;
508
509 if (pSrc != pDest) {
510 for (; pDest < &_erelocate;) {
511 *pDest++ = *pSrc++;
512 }
513 }
514
515 /* Clear the zero segment */
516 for (pDest = &_szero; pDest < &_ezero;) {
517 *pDest++ = 0;
518 }
519
520 /* Set the vector table base address */
521 pSrc = (uint32_t *) & _sfixed;
522 SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);
523
524#if __FPU_USED
525 /* Enable FPU */
526 SCB->CPACR |= (0xFu << 20);
527 __DSB();
528 __ISB();
529#endif
530
531 /* Initialize the C library */
532 __libc_init_array();
533
534 /* Branch to main function */
535 main();
536
537 /* Infinite loop */
538 while (1);
539}
540
541/**
542 * \brief Default interrupt handler for unused IRQs.
543 */
544void Dummy_Handler(void)
545{
546 while (1) {
547 }
548}
diff --git a/tmk_core/protocol/arm_atsam/usb/compiler.h b/tmk_core/protocol/arm_atsam/usb/compiler.h
new file mode 100644
index 000000000..d33843986
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/compiler.h
@@ -0,0 +1,1177 @@
1/**
2 * \file
3 *
4 * \brief Commonly used includes, types and macros.
5 *
6 * Copyright (C) 2012-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * 3. The name of Atmel may not be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * 4. This software may only be redistributed and used in connection with an
24 * Atmel microcontroller product.
25 *
26 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
29 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 * \asf_license_stop
39 *
40 */
41/*
42 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
43 */
44
45#ifndef UTILS_COMPILER_H_INCLUDED
46#define UTILS_COMPILER_H_INCLUDED
47
48/**
49 * \defgroup group_sam0_utils Compiler abstraction layer and code utilities
50 *
51 * Compiler abstraction layer and code utilities for Cortex-M0+ based Atmel SAM devices.
52 * This module provides various abstraction layers and utilities to make code compatible between different compilers.
53 *
54 * @{
55 */
56
57#if (defined __ICCARM__)
58# include <intrinsics.h>
59#endif
60
61#include <stddef.h>
62//#include <parts.h>
63//#include <status_codes.h>
64//#include <preprocessor.h>
65//#include <io.h>
66
67#ifndef __ASSEMBLY__
68
69#include <stdio.h>
70#include <stdbool.h>
71#include <stdint.h>
72#include <stdlib.h>
73
74/**
75 * \def UNUSED
76 * \brief Marking \a v as a unused parameter or value.
77 */
78#define UNUSED(v) (void)(v)
79
80/**
81 * \def barrier
82 * \brief Memory barrier
83 */
84#ifdef __GNUC__
85# define barrier() asm volatile("" ::: "memory")
86#else
87# define barrier() asm ("")
88#endif
89
90/**
91 * \brief Emit the compiler pragma \a arg.
92 *
93 * \param[in] arg The pragma directive as it would appear after \e \#pragma
94 * (i.e. not stringified).
95 */
96#define COMPILER_PRAGMA(arg) _Pragma(#arg)
97
98/**
99 * \def COMPILER_PACK_SET(alignment)
100 * \brief Set maximum alignment for subsequent struct and union definitions to \a alignment.
101 */
102#define COMPILER_PACK_SET(alignment) COMPILER_PRAGMA(pack(alignment))
103
104/**
105 * \def COMPILER_PACK_RESET()
106 * \brief Set default alignment for subsequent struct and union definitions.
107 */
108#define COMPILER_PACK_RESET() COMPILER_PRAGMA(pack())
109
110
111/**
112 * \brief Set aligned boundary.
113 */
114#if (defined __GNUC__) || (defined __CC_ARM)
115# define COMPILER_ALIGNED(a) __attribute__((__aligned__(a)))
116#elif (defined __ICCARM__)
117# define COMPILER_ALIGNED(a) COMPILER_PRAGMA(data_alignment = a)
118#endif
119
120/**
121 * \brief Set word-aligned boundary.
122 */
123#if (defined __GNUC__) || defined(__CC_ARM)
124#define COMPILER_WORD_ALIGNED __attribute__((__aligned__(4)))
125#elif (defined __ICCARM__)
126#define COMPILER_WORD_ALIGNED COMPILER_PRAGMA(data_alignment = 4)
127#endif
128
129/**
130 * \def __always_inline
131 * \brief The function should always be inlined.
132 *
133 * This annotation instructs the compiler to ignore its inlining
134 * heuristics and inline the function no matter how big it thinks it
135 * becomes.
136 */
137#if defined(__CC_ARM)
138# define __always_inline __forceinline
139#elif (defined __GNUC__)
140# define __always_inline __attribute__((__always_inline__))
141#elif (defined __ICCARM__)
142# define __always_inline _Pragma("inline=forced")
143#endif
144
145/**
146 * \def __no_inline
147 * \brief The function should never be inlined
148 *
149 * This annotation instructs the compiler to ignore its inlining
150 * heuristics and not inline the function no matter how small it thinks it
151 * becomes.
152 */
153#if defined(__CC_ARM)
154# define __no_inline __attribute__((noinline))
155#elif (defined __GNUC__)
156# define __no_inline __attribute__((noinline))
157#elif (defined __ICCARM__)
158# define __no_inline _Pragma("inline=never")
159#endif
160
161
162/** \brief This macro is used to test fatal errors.
163 *
164 * The macro tests if the expression is false. If it is, a fatal error is
165 * detected and the application hangs up. If \c TEST_SUITE_DEFINE_ASSERT_MACRO
166 * is defined, a unit test version of the macro is used, to allow execution
167 * of further tests after a false expression.
168 *
169 * \param[in] expr Expression to evaluate and supposed to be nonzero.
170 */
171#if defined(_ASSERT_ENABLE_)
172# if defined(TEST_SUITE_DEFINE_ASSERT_MACRO)
173# include "unit_test/suite.h"
174# else
175# undef TEST_SUITE_DEFINE_ASSERT_MACRO
176# define Assert(expr) \
177 {\
178 if (!(expr)) asm("BKPT #0");\
179 }
180# endif
181#else
182# define Assert(expr) ((void) 0)
183#endif
184
185/* Define WEAK attribute */
186#if defined ( __CC_ARM )
187# define WEAK __attribute__ ((weak))
188#elif defined ( __ICCARM__ )
189# define WEAK __weak
190#elif defined ( __GNUC__ )
191# define WEAK __attribute__ ((weak))
192#endif
193
194/* Define NO_INIT attribute */
195#if defined ( __CC_ARM )
196# define NO_INIT __attribute__((zero_init))
197#elif defined ( __ICCARM__ )
198# define NO_INIT __no_init
199#elif defined ( __GNUC__ )
200# define NO_INIT __attribute__((section(".no_init")))
201#endif
202
203//#include "interrupt.h"
204
205/** \name Usual Types
206 * @{ */
207#ifndef __cplusplus
208# if !defined(__bool_true_false_are_defined)
209typedef unsigned char bool;
210# endif
211#endif
212typedef uint16_t le16_t;
213typedef uint16_t be16_t;
214typedef uint32_t le32_t;
215typedef uint32_t be32_t;
216typedef uint32_t iram_size_t;
217/** @} */
218
219/** \name Aliasing Aggregate Types
220 * @{ */
221
222/** 16-bit union. */
223typedef union
224{
225 int16_t s16;
226 uint16_t u16;
227 int8_t s8[2];
228 uint8_t u8[2];
229} Union16;
230
231/** 32-bit union. */
232typedef union
233{
234 int32_t s32;
235 uint32_t u32;
236 int16_t s16[2];
237 uint16_t u16[2];
238 int8_t s8[4];
239 uint8_t u8[4];
240} Union32;
241
242/** 64-bit union. */
243typedef union
244{
245 int64_t s64;
246 uint64_t u64;
247 int32_t s32[2];
248 uint32_t u32[2];
249 int16_t s16[4];
250 uint16_t u16[4];
251 int8_t s8[8];
252 uint8_t u8[8];
253} Union64;
254
255/** Union of pointers to 64-, 32-, 16- and 8-bit unsigned integers. */
256typedef union
257{
258 int64_t *s64ptr;
259 uint64_t *u64ptr;
260 int32_t *s32ptr;
261 uint32_t *u32ptr;
262 int16_t *s16ptr;
263 uint16_t *u16ptr;
264 int8_t *s8ptr;
265 uint8_t *u8ptr;
266} UnionPtr;
267
268/** Union of pointers to volatile 64-, 32-, 16- and 8-bit unsigned integers. */
269typedef union
270{
271 volatile int64_t *s64ptr;
272 volatile uint64_t *u64ptr;
273 volatile int32_t *s32ptr;
274 volatile uint32_t *u32ptr;
275 volatile int16_t *s16ptr;
276 volatile uint16_t *u16ptr;
277 volatile int8_t *s8ptr;
278 volatile uint8_t *u8ptr;
279} UnionVPtr;
280
281/** Union of pointers to constant 64-, 32-, 16- and 8-bit unsigned integers. */
282typedef union
283{
284 const int64_t *s64ptr;
285 const uint64_t *u64ptr;
286 const int32_t *s32ptr;
287 const uint32_t *u32ptr;
288 const int16_t *s16ptr;
289 const uint16_t *u16ptr;
290 const int8_t *s8ptr;
291 const uint8_t *u8ptr;
292} UnionCPtr;
293
294/** Union of pointers to constant volatile 64-, 32-, 16- and 8-bit unsigned integers. */
295typedef union
296{
297 const volatile int64_t *s64ptr;
298 const volatile uint64_t *u64ptr;
299 const volatile int32_t *s32ptr;
300 const volatile uint32_t *u32ptr;
301 const volatile int16_t *s16ptr;
302 const volatile uint16_t *u16ptr;
303 const volatile int8_t *s8ptr;
304 const volatile uint8_t *u8ptr;
305} UnionCVPtr;
306
307/** Structure of pointers to 64-, 32-, 16- and 8-bit unsigned integers. */
308typedef struct
309{
310 int64_t *s64ptr;
311 uint64_t *u64ptr;
312 int32_t *s32ptr;
313 uint32_t *u32ptr;
314 int16_t *s16ptr;
315 uint16_t *u16ptr;
316 int8_t *s8ptr;
317 uint8_t *u8ptr;
318} StructPtr;
319
320/** Structure of pointers to volatile 64-, 32-, 16- and 8-bit unsigned integers. */
321typedef struct
322{
323 volatile int64_t *s64ptr;
324 volatile uint64_t *u64ptr;
325 volatile int32_t *s32ptr;
326 volatile uint32_t *u32ptr;
327 volatile int16_t *s16ptr;
328 volatile uint16_t *u16ptr;
329 volatile int8_t *s8ptr;
330 volatile uint8_t *u8ptr;
331} StructVPtr;
332
333/** Structure of pointers to constant 64-, 32-, 16- and 8-bit unsigned integers. */
334typedef struct
335{
336 const int64_t *s64ptr;
337 const uint64_t *u64ptr;
338 const int32_t *s32ptr;
339 const uint32_t *u32ptr;
340 const int16_t *s16ptr;
341 const uint16_t *u16ptr;
342 const int8_t *s8ptr;
343 const uint8_t *u8ptr;
344} StructCPtr;
345
346/** Structure of pointers to constant volatile 64-, 32-, 16- and 8-bit unsigned integers. */
347typedef struct
348{
349 const volatile int64_t *s64ptr;
350 const volatile uint64_t *u64ptr;
351 const volatile int32_t *s32ptr;
352 const volatile uint32_t *u32ptr;
353 const volatile int16_t *s16ptr;
354 const volatile uint16_t *u16ptr;
355 const volatile int8_t *s8ptr;
356 const volatile uint8_t *u8ptr;
357} StructCVPtr;
358
359/** @} */
360
361#endif /* #ifndef __ASSEMBLY__ */
362
363/** \name Usual Constants
364 * @{ */
365//kmod #define DISABLE 0
366//kmod #define ENABLE 1
367
368#ifndef __cplusplus
369# if !defined(__bool_true_false_are_defined)
370# define false 0
371# define true 1
372# endif
373#endif
374/** @} */
375
376#ifndef __ASSEMBLY__
377
378/** \name Optimization Control
379 * @{ */
380
381/**
382 * \def likely(exp)
383 * \brief The expression \a exp is likely to be true
384 */
385#if !defined(likely) || defined(__DOXYGEN__)
386# define likely(exp) (exp)
387#endif
388
389/**
390 * \def unlikely(exp)
391 * \brief The expression \a exp is unlikely to be true
392 */
393#if !defined(unlikely) || defined(__DOXYGEN__)
394# define unlikely(exp) (exp)
395#endif
396
397/**
398 * \def is_constant(exp)
399 * \brief Determine if an expression evaluates to a constant value.
400 *
401 * \param[in] exp Any expression
402 *
403 * \return true if \a exp is constant, false otherwise.
404 */
405#if (defined __GNUC__) || (defined __CC_ARM)
406# define is_constant(exp) __builtin_constant_p(exp)
407#else
408# define is_constant(exp) (0)
409#endif
410
411/** @} */
412
413/** \name Bit-Field Handling
414 * @{ */
415
416/** \brief Reads the bits of a value specified by a given bit-mask.
417 *
418 * \param[in] value Value to read bits from.
419 * \param[in] mask Bit-mask indicating bits to read.
420 *
421 * \return Read bits.
422 */
423#define Rd_bits( value, mask) ((value) & (mask))
424
425/** \brief Writes the bits of a C lvalue specified by a given bit-mask.
426 *
427 * \param[in] lvalue C lvalue to write bits to.
428 * \param[in] mask Bit-mask indicating bits to write.
429 * \param[in] bits Bits to write.
430 *
431 * \return Resulting value with written bits.
432 */
433#define Wr_bits(lvalue, mask, bits) ((lvalue) = ((lvalue) & ~(mask)) |\
434 ((bits ) & (mask)))
435
436/** \brief Tests the bits of a value specified by a given bit-mask.
437 *
438 * \param[in] value Value of which to test bits.
439 * \param[in] mask Bit-mask indicating bits to test.
440 *
441 * \return \c 1 if at least one of the tested bits is set, else \c 0.
442 */
443#define Tst_bits( value, mask) (Rd_bits(value, mask) != 0)
444
445/** \brief Clears the bits of a C lvalue specified by a given bit-mask.
446 *
447 * \param[in] lvalue C lvalue of which to clear bits.
448 * \param[in] mask Bit-mask indicating bits to clear.
449 *
450 * \return Resulting value with cleared bits.
451 */
452#define Clr_bits(lvalue, mask) ((lvalue) &= ~(mask))
453
454/** \brief Sets the bits of a C lvalue specified by a given bit-mask.
455 *
456 * \param[in] lvalue C lvalue of which to set bits.
457 * \param[in] mask Bit-mask indicating bits to set.
458 *
459 * \return Resulting value with set bits.
460 */
461#define Set_bits(lvalue, mask) ((lvalue) |= (mask))
462
463/** \brief Toggles the bits of a C lvalue specified by a given bit-mask.
464 *
465 * \param[in] lvalue C lvalue of which to toggle bits.
466 * \param[in] mask Bit-mask indicating bits to toggle.
467 *
468 * \return Resulting value with toggled bits.
469 */
470#define Tgl_bits(lvalue, mask) ((lvalue) ^= (mask))
471
472/** \brief Reads the bit-field of a value specified by a given bit-mask.
473 *
474 * \param[in] value Value to read a bit-field from.
475 * \param[in] mask Bit-mask indicating the bit-field to read.
476 *
477 * \return Read bit-field.
478 */
479#define Rd_bitfield( value, mask) (Rd_bits( value, mask) >> ctz(mask))
480
481/** \brief Writes the bit-field of a C lvalue specified by a given bit-mask.
482 *
483 * \param[in] lvalue C lvalue to write a bit-field to.
484 * \param[in] mask Bit-mask indicating the bit-field to write.
485 * \param[in] bitfield Bit-field to write.
486 *
487 * \return Resulting value with written bit-field.
488 */
489#define Wr_bitfield(lvalue, mask, bitfield) (Wr_bits(lvalue, mask, (uint32_t)(bitfield) << ctz(mask)))
490
491/** @} */
492
493
494/** \name Zero-Bit Counting
495 *
496 * Under GCC, __builtin_clz and __builtin_ctz behave like macros when
497 * applied to constant expressions (values known at compile time), so they are
498 * more optimized than the use of the corresponding assembly instructions and
499 * they can be used as constant expressions e.g. to initialize objects having
500 * static storage duration, and like the corresponding assembly instructions
501 * when applied to non-constant expressions (values unknown at compile time), so
502 * they are more optimized than an assembly periphrasis. Hence, clz and ctz
503 * ensure a possible and optimized behavior for both constant and non-constant
504 * expressions.
505 *
506 * @{ */
507
508/** \brief Counts the leading zero bits of the given value considered as a 32-bit integer.
509 *
510 * \param[in] u Value of which to count the leading zero bits.
511 *
512 * \return The count of leading zero bits in \a u.
513 */
514#if (defined __GNUC__) || (defined __CC_ARM)
515# define clz(u) ((u) ? __builtin_clz(u) : 32)
516#else
517# define clz(u) (((u) == 0) ? 32 : \
518 ((u) & (1ul << 31)) ? 0 : \
519 ((u) & (1ul << 30)) ? 1 : \
520 ((u) & (1ul << 29)) ? 2 : \
521 ((u) & (1ul << 28)) ? 3 : \
522 ((u) & (1ul << 27)) ? 4 : \
523 ((u) & (1ul << 26)) ? 5 : \
524 ((u) & (1ul << 25)) ? 6 : \
525 ((u) & (1ul << 24)) ? 7 : \
526 ((u) & (1ul << 23)) ? 8 : \
527 ((u) & (1ul << 22)) ? 9 : \
528 ((u) & (1ul << 21)) ? 10 : \
529 ((u) & (1ul << 20)) ? 11 : \
530 ((u) & (1ul << 19)) ? 12 : \
531 ((u) & (1ul << 18)) ? 13 : \
532 ((u) & (1ul << 17)) ? 14 : \
533 ((u) & (1ul << 16)) ? 15 : \
534 ((u) & (1ul << 15)) ? 16 : \
535 ((u) & (1ul << 14)) ? 17 : \
536 ((u) & (1ul << 13)) ? 18 : \
537 ((u) & (1ul << 12)) ? 19 : \
538 ((u) & (1ul << 11)) ? 20 : \
539 ((u) & (1ul << 10)) ? 21 : \
540 ((u) & (1ul << 9)) ? 22 : \
541 ((u) & (1ul << 8)) ? 23 : \
542 ((u) & (1ul << 7)) ? 24 : \
543 ((u) & (1ul << 6)) ? 25 : \
544 ((u) & (1ul << 5)) ? 26 : \
545 ((u) & (1ul << 4)) ? 27 : \
546 ((u) & (1ul << 3)) ? 28 : \
547 ((u) & (1ul << 2)) ? 29 : \
548 ((u) & (1ul << 1)) ? 30 : \
549 31)
550#endif
551
552/** \brief Counts the trailing zero bits of the given value considered as a 32-bit integer.
553 *
554 * \param[in] u Value of which to count the trailing zero bits.
555 *
556 * \return The count of trailing zero bits in \a u.
557 */
558#if (defined __GNUC__) || (defined __CC_ARM)
559# define ctz(u) ((u) ? __builtin_ctz(u) : 32)
560#else
561# define ctz(u) ((u) & (1ul << 0) ? 0 : \
562 (u) & (1ul << 1) ? 1 : \
563 (u) & (1ul << 2) ? 2 : \
564 (u) & (1ul << 3) ? 3 : \
565 (u) & (1ul << 4) ? 4 : \
566 (u) & (1ul << 5) ? 5 : \
567 (u) & (1ul << 6) ? 6 : \
568 (u) & (1ul << 7) ? 7 : \
569 (u) & (1ul << 8) ? 8 : \
570 (u) & (1ul << 9) ? 9 : \
571 (u) & (1ul << 10) ? 10 : \
572 (u) & (1ul << 11) ? 11 : \
573 (u) & (1ul << 12) ? 12 : \
574 (u) & (1ul << 13) ? 13 : \
575 (u) & (1ul << 14) ? 14 : \
576 (u) & (1ul << 15) ? 15 : \
577 (u) & (1ul << 16) ? 16 : \
578 (u) & (1ul << 17) ? 17 : \
579 (u) & (1ul << 18) ? 18 : \
580 (u) & (1ul << 19) ? 19 : \
581 (u) & (1ul << 20) ? 20 : \
582 (u) & (1ul << 21) ? 21 : \
583 (u) & (1ul << 22) ? 22 : \
584 (u) & (1ul << 23) ? 23 : \
585 (u) & (1ul << 24) ? 24 : \
586 (u) & (1ul << 25) ? 25 : \
587 (u) & (1ul << 26) ? 26 : \
588 (u) & (1ul << 27) ? 27 : \
589 (u) & (1ul << 28) ? 28 : \
590 (u) & (1ul << 29) ? 29 : \
591 (u) & (1ul << 30) ? 30 : \
592 (u) & (1ul << 31) ? 31 : \
593 32)
594#endif
595
596/** @} */
597
598
599/** \name Bit Reversing
600 * @{ */
601
602/** \brief Reverses the bits of \a u8.
603 *
604 * \param[in] u8 U8 of which to reverse the bits.
605 *
606 * \return Value resulting from \a u8 with reversed bits.
607 */
608#define bit_reverse8(u8) ((U8)(bit_reverse32((U8)(u8)) >> 24))
609
610/** \brief Reverses the bits of \a u16.
611 *
612 * \param[in] u16 U16 of which to reverse the bits.
613 *
614 * \return Value resulting from \a u16 with reversed bits.
615 */
616#define bit_reverse16(u16) ((uint16_t)(bit_reverse32((uint16_t)(u16)) >> 16))
617
618/** \brief Reverses the bits of \a u32.
619 *
620 * \param[in] u32 U32 of which to reverse the bits.
621 *
622 * \return Value resulting from \a u32 with reversed bits.
623 */
624#define bit_reverse32(u32) __RBIT(u32)
625
626/** \brief Reverses the bits of \a u64.
627 *
628 * \param[in] u64 U64 of which to reverse the bits.
629 *
630 * \return Value resulting from \a u64 with reversed bits.
631 */
632#define bit_reverse64(u64) ((uint64_t)(((uint64_t)bit_reverse32((uint64_t)(u64) >> 32)) |\
633 ((uint64_t)bit_reverse32((uint64_t)(u64)) << 32)))
634
635/** @} */
636
637
638/** \name Alignment
639 * @{ */
640
641/** \brief Tests alignment of the number \a val with the \a n boundary.
642 *
643 * \param[in] val Input value.
644 * \param[in] n Boundary.
645 *
646 * \return \c 1 if the number \a val is aligned with the \a n boundary, else \c 0.
647 */
648#define Test_align(val, n) (!Tst_bits( val, (n) - 1 ) )
649
650/** \brief Gets alignment of the number \a val with respect to the \a n boundary.
651 *
652 * \param[in] val Input value.
653 * \param[in] n Boundary.
654 *
655 * \return Alignment of the number \a val with respect to the \a n boundary.
656 */
657#define Get_align(val, n) ( Rd_bits( val, (n) - 1 ) )
658
659/** \brief Sets alignment of the lvalue number \a lval to \a alg with respect to the \a n boundary.
660 *
661 * \param[in] lval Input/output lvalue.
662 * \param[in] n Boundary.
663 * \param[in] alg Alignment.
664 *
665 * \return New value of \a lval resulting from its alignment set to \a alg with respect to the \a n boundary.
666 */
667#define Set_align(lval, n, alg) ( Wr_bits(lval, (n) - 1, alg) )
668
669/** \brief Aligns the number \a val with the upper \a n boundary.
670 *
671 * \param[in] val Input value.
672 * \param[in] n Boundary.
673 *
674 * \return Value resulting from the number \a val aligned with the upper \a n boundary.
675 */
676#define Align_up( val, n) (((val) + ((n) - 1)) & ~((n) - 1))
677
678/** \brief Aligns the number \a val with the lower \a n boundary.
679 *
680 * \param[in] val Input value.
681 * \param[in] n Boundary.
682 *
683 * \return Value resulting from the number \a val aligned with the lower \a n boundary.
684 */
685#define Align_down(val, n) ( (val) & ~((n) - 1))
686
687/** @} */
688
689
690/** \name Mathematics
691 *
692 * The same considerations as for clz and ctz apply here but GCC does not
693 * provide built-in functions to access the assembly instructions abs, min and
694 * max and it does not produce them by itself in most cases, so two sets of
695 * macros are defined here:
696 * - Abs, Min and Max to apply to constant expressions (values known at
697 * compile time);
698 * - abs, min and max to apply to non-constant expressions (values unknown at
699 * compile time), abs is found in stdlib.h.
700 *
701 * @{ */
702
703/** \brief Takes the absolute value of \a a.
704 *
705 * \param[in] a Input value.
706 *
707 * \return Absolute value of \a a.
708 *
709 * \note More optimized if only used with values known at compile time.
710 */
711#define Abs(a) (((a) < 0 ) ? -(a) : (a))
712
713#ifndef __cplusplus
714/** \brief Takes the minimal value of \a a and \a b.
715 *
716 * \param[in] a Input value.
717 * \param[in] b Input value.
718 *
719 * \return Minimal value of \a a and \a b.
720 *
721 * \note More optimized if only used with values known at compile time.
722 */
723#define Min(a, b) (((a) < (b)) ? (a) : (b))
724
725/** \brief Takes the maximal value of \a a and \a b.
726 *
727 * \param[in] a Input value.
728 * \param[in] b Input value.
729 *
730 * \return Maximal value of \a a and \a b.
731 *
732 * \note More optimized if only used with values known at compile time.
733 */
734#define Max(a, b) (((a) > (b)) ? (a) : (b))
735
736/** \brief Takes the minimal value of \a a and \a b.
737 *
738 * \param[in] a Input value.
739 * \param[in] b Input value.
740 *
741 * \return Minimal value of \a a and \a b.
742 *
743 * \note More optimized if only used with values unknown at compile time.
744 */
745#define min(a, b) Min(a, b)
746
747/** \brief Takes the maximal value of \a a and \a b.
748 *
749 * \param[in] a Input value.
750 * \param[in] b Input value.
751 *
752 * \return Maximal value of \a a and \a b.
753 *
754 * \note More optimized if only used with values unknown at compile time.
755 */
756#define max(a, b) Max(a, b)
757#endif
758
759/** @} */
760
761
762/** \brief Calls the routine at address \a addr.
763 *
764 * It generates a long call opcode.
765 *
766 * For example, `Long_call(0x80000000)' generates a software reset on a UC3 if
767 * it is invoked from the CPU supervisor mode.
768 *
769 * \param[in] addr Address of the routine to call.
770 *
771 * \note It may be used as a long jump opcode in some special cases.
772 */
773#define Long_call(addr) ((*(void (*)(void))(addr))())
774
775
776/** \name MCU Endianism Handling
777 * ARM is MCU little endian.
778 *
779 * @{ */
780#define BE16(x) swap16(x)
781#define LE16(x) (x)
782
783#define le16_to_cpu(x) (x)
784#define cpu_to_le16(x) (x)
785#define LE16_TO_CPU(x) (x)
786#define CPU_TO_LE16(x) (x)
787
788#define be16_to_cpu(x) swap16(x)
789#define cpu_to_be16(x) swap16(x)
790#define BE16_TO_CPU(x) swap16(x)
791#define CPU_TO_BE16(x) swap16(x)
792
793#define le32_to_cpu(x) (x)
794#define cpu_to_le32(x) (x)
795#define LE32_TO_CPU(x) (x)
796#define CPU_TO_LE32(x) (x)
797
798#define be32_to_cpu(x) swap32(x)
799#define cpu_to_be32(x) swap32(x)
800#define BE32_TO_CPU(x) swap32(x)
801#define CPU_TO_BE32(x) swap32(x)
802/** @} */
803
804
805/** \name Endianism Conversion
806 *
807 * The same considerations as for clz and ctz apply here but GCC's
808 * __builtin_bswap_32 and __builtin_bswap_64 do not behave like macros when
809 * applied to constant expressions, so two sets of macros are defined here:
810 * - Swap16, Swap32 and Swap64 to apply to constant expressions (values known
811 * at compile time);
812 * - swap16, swap32 and swap64 to apply to non-constant expressions (values
813 * unknown at compile time).
814 *
815 * @{ */
816
817/** \brief Toggles the endianism of \a u16 (by swapping its bytes).
818 *
819 * \param[in] u16 U16 of which to toggle the endianism.
820 *
821 * \return Value resulting from \a u16 with toggled endianism.
822 *
823 * \note More optimized if only used with values known at compile time.
824 */
825#define Swap16(u16) ((uint16_t)(((uint16_t)(u16) >> 8) |\
826 ((uint16_t)(u16) << 8)))
827
828/** \brief Toggles the endianism of \a u32 (by swapping its bytes).
829 *
830 * \param[in] u32 U32 of which to toggle the endianism.
831 *
832 * \return Value resulting from \a u32 with toggled endianism.
833 *
834 * \note More optimized if only used with values known at compile time.
835 */
836#define Swap32(u32) ((uint32_t)(((uint32_t)Swap16((uint32_t)(u32) >> 16)) |\
837 ((uint32_t)Swap16((uint32_t)(u32)) << 16)))
838
839/** \brief Toggles the endianism of \a u64 (by swapping its bytes).
840 *
841 * \param[in] u64 U64 of which to toggle the endianism.
842 *
843 * \return Value resulting from \a u64 with toggled endianism.
844 *
845 * \note More optimized if only used with values known at compile time.
846 */
847#define Swap64(u64) ((uint64_t)(((uint64_t)Swap32((uint64_t)(u64) >> 32)) |\
848 ((uint64_t)Swap32((uint64_t)(u64)) << 32)))
849
850/** \brief Toggles the endianism of \a u16 (by swapping its bytes).
851 *
852 * \param[in] u16 U16 of which to toggle the endianism.
853 *
854 * \return Value resulting from \a u16 with toggled endianism.
855 *
856 * \note More optimized if only used with values unknown at compile time.
857 */
858#define swap16(u16) Swap16(u16)
859
860/** \brief Toggles the endianism of \a u32 (by swapping its bytes).
861 *
862 * \param[in] u32 U32 of which to toggle the endianism.
863 *
864 * \return Value resulting from \a u32 with toggled endianism.
865 *
866 * \note More optimized if only used with values unknown at compile time.
867 */
868#if (defined __GNUC__)
869# define swap32(u32) ((uint32_t)__builtin_bswap32((uint32_t)(u32)))
870#else
871# define swap32(u32) Swap32(u32)
872#endif
873
874/** \brief Toggles the endianism of \a u64 (by swapping its bytes).
875 *
876 * \param[in] u64 U64 of which to toggle the endianism.
877 *
878 * \return Value resulting from \a u64 with toggled endianism.
879 *
880 * \note More optimized if only used with values unknown at compile time.
881 */
882#if (defined __GNUC__)
883# define swap64(u64) ((uint64_t)__builtin_bswap64((uint64_t)(u64)))
884#else
885# define swap64(u64) ((uint64_t)(((uint64_t)swap32((uint64_t)(u64) >> 32)) |\
886 ((uint64_t)swap32((uint64_t)(u64)) << 32)))
887#endif
888
889/** @} */
890
891
892/** \name Target Abstraction
893 *
894 * @{ */
895
896#define _GLOBEXT_ extern /**< extern storage-class specifier. */
897#define _CONST_TYPE_ const /**< const type qualifier. */
898#define _MEM_TYPE_SLOW_ /**< Slow memory type. */
899#define _MEM_TYPE_MEDFAST_ /**< Fairly fast memory type. */
900#define _MEM_TYPE_FAST_ /**< Fast memory type. */
901
902#define memcmp_ram2ram memcmp /**< Target-specific memcmp of RAM to RAM. */
903#define memcmp_code2ram memcmp /**< Target-specific memcmp of RAM to NVRAM. */
904#define memcpy_ram2ram memcpy /**< Target-specific memcpy from RAM to RAM. */
905#define memcpy_code2ram memcpy /**< Target-specific memcpy from NVRAM to RAM. */
906
907/** @} */
908
909/**
910 * \brief Calculate \f$ \left\lceil \frac{a}{b} \right\rceil \f$ using
911 * integer arithmetic.
912 *
913 * \param[in] a An integer
914 * \param[in] b Another integer
915 *
916 * \return (\a a / \a b) rounded up to the nearest integer.
917 */
918#define div_ceil(a, b) (((a) + (b) - 1) / (b))
919
920#endif /* #ifndef __ASSEMBLY__ */
921#ifdef __ICCARM__
922/** \name Compiler Keywords
923 *
924 * Port of some keywords from GCC to IAR Embedded Workbench.
925 *
926 * @{ */
927
928#define __asm__ asm
929#define __inline__ inline
930#define __volatile__
931
932/** @} */
933
934#endif
935
936#define FUNC_PTR void *
937/**
938 * \def unused
939 * \brief Marking \a v as a unused parameter or value.
940 */
941#define unused(v) do { (void)(v); } while(0)
942
943/* Define RAMFUNC attribute */
944#if defined ( __CC_ARM ) /* Keil uVision 4 */
945# define RAMFUNC __attribute__ ((section(".ramfunc")))
946#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
947# define RAMFUNC __ramfunc
948#elif defined ( __GNUC__ ) /* GCC CS3 2009q3-68 */
949# define RAMFUNC __attribute__ ((section(".ramfunc")))
950#endif
951
952/* Define OPTIMIZE_HIGH attribute */
953#if defined ( __CC_ARM ) /* Keil uVision 4 */
954# define OPTIMIZE_HIGH _Pragma("O3")
955#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
956# define OPTIMIZE_HIGH _Pragma("optimize=high")
957#elif defined ( __GNUC__ ) /* GCC CS3 2009q3-68 */
958# define OPTIMIZE_HIGH __attribute__((optimize("s")))
959#endif
960//kmod #define PASS 0
961//kmod #define FAIL 1
962//kmod #define LOW 0
963//kmod #define HIGH 1
964
965typedef int8_t S8 ; //!< 8-bit signed integer.
966typedef uint8_t U8 ; //!< 8-bit unsigned integer.
967typedef int16_t S16; //!< 16-bit signed integer.
968typedef uint16_t U16; //!< 16-bit unsigned integer.
969typedef int32_t S32; //!< 32-bit signed integer.
970typedef uint32_t U32; //!< 32-bit unsigned integer.
971typedef int64_t S64; //!< 64-bit signed integer.
972typedef uint64_t U64; //!< 64-bit unsigned integer.
973typedef float F32; //!< 32-bit floating-point number.
974typedef double F64; //!< 64-bit floating-point number.
975
976#define MSB(u16) (((U8 *)&(u16))[1]) //!< Most significant byte of \a u16.
977#define LSB(u16) (((U8 *)&(u16))[0]) //!< Least significant byte of \a u16.
978
979#define MSH(u32) (((U16 *)&(u32))[1]) //!< Most significant half-word of \a u32.
980#define LSH(u32) (((U16 *)&(u32))[0]) //!< Least significant half-word of \a u32.
981#define MSB0W(u32) (((U8 *)&(u32))[3]) //!< Most significant byte of 1st rank of \a u32.
982#define MSB1W(u32) (((U8 *)&(u32))[2]) //!< Most significant byte of 2nd rank of \a u32.
983#define MSB2W(u32) (((U8 *)&(u32))[1]) //!< Most significant byte of 3rd rank of \a u32.
984#define MSB3W(u32) (((U8 *)&(u32))[0]) //!< Most significant byte of 4th rank of \a u32.
985#define LSB3W(u32) MSB0W(u32) //!< Least significant byte of 4th rank of \a u32.
986#define LSB2W(u32) MSB1W(u32) //!< Least significant byte of 3rd rank of \a u32.
987#define LSB1W(u32) MSB2W(u32) //!< Least significant byte of 2nd rank of \a u32.
988#define LSB0W(u32) MSB3W(u32) //!< Least significant byte of 1st rank of \a u32.
989
990#define MSW(u64) (((U32 *)&(u64))[1]) //!< Most significant word of \a u64.
991#define LSW(u64) (((U32 *)&(u64))[0]) //!< Least significant word of \a u64.
992#define MSH0(u64) (((U16 *)&(u64))[3]) //!< Most significant half-word of 1st rank of \a u64.
993#define MSH1(u64) (((U16 *)&(u64))[2]) //!< Most significant half-word of 2nd rank of \a u64.
994#define MSH2(u64) (((U16 *)&(u64))[1]) //!< Most significant half-word of 3rd rank of \a u64.
995#define MSH3(u64) (((U16 *)&(u64))[0]) //!< Most significant half-word of 4th rank of \a u64.
996#define LSH3(u64) MSH0(u64) //!< Least significant half-word of 4th rank of \a u64.
997#define LSH2(u64) MSH1(u64) //!< Least significant half-word of 3rd rank of \a u64.
998#define LSH1(u64) MSH2(u64) //!< Least significant half-word of 2nd rank of \a u64.
999#define LSH0(u64) MSH3(u64) //!< Least significant half-word of 1st rank of \a u64.
1000#define MSB0D(u64) (((U8 *)&(u64))[7]) //!< Most significant byte of 1st rank of \a u64.
1001#define MSB1D(u64) (((U8 *)&(u64))[6]) //!< Most significant byte of 2nd rank of \a u64.
1002#define MSB2D(u64) (((U8 *)&(u64))[5]) //!< Most significant byte of 3rd rank of \a u64.
1003#define MSB3D(u64) (((U8 *)&(u64))[4]) //!< Most significant byte of 4th rank of \a u64.
1004#define MSB4D(u64) (((U8 *)&(u64))[3]) //!< Most significant byte of 5th rank of \a u64.
1005#define MSB5D(u64) (((U8 *)&(u64))[2]) //!< Most significant byte of 6th rank of \a u64.
1006#define MSB6D(u64) (((U8 *)&(u64))[1]) //!< Most significant byte of 7th rank of \a u64.
1007#define MSB7D(u64) (((U8 *)&(u64))[0]) //!< Most significant byte of 8th rank of \a u64.
1008#define LSB7D(u64) MSB0D(u64) //!< Least significant byte of 8th rank of \a u64.
1009#define LSB6D(u64) MSB1D(u64) //!< Least significant byte of 7th rank of \a u64.
1010#define LSB5D(u64) MSB2D(u64) //!< Least significant byte of 6th rank of \a u64.
1011#define LSB4D(u64) MSB3D(u64) //!< Least significant byte of 5th rank of \a u64.
1012#define LSB3D(u64) MSB4D(u64) //!< Least significant byte of 4th rank of \a u64.
1013#define LSB2D(u64) MSB5D(u64) //!< Least significant byte of 3rd rank of \a u64.
1014#define LSB1D(u64) MSB6D(u64) //!< Least significant byte of 2nd rank of \a u64.
1015#define LSB0D(u64) MSB7D(u64) //!< Least significant byte of 1st rank of \a u64.
1016
1017#define LSB0(u32) LSB0W(u32) //!< Least significant byte of 1st rank of \a u32.
1018#define LSB1(u32) LSB1W(u32) //!< Least significant byte of 2nd rank of \a u32.
1019#define LSB2(u32) LSB2W(u32) //!< Least significant byte of 3rd rank of \a u32.
1020#define LSB3(u32) LSB3W(u32) //!< Least significant byte of 4th rank of \a u32.
1021#define MSB3(u32) MSB3W(u32) //!< Most significant byte of 4th rank of \a u32.
1022#define MSB2(u32) MSB2W(u32) //!< Most significant byte of 3rd rank of \a u32.
1023#define MSB1(u32) MSB1W(u32) //!< Most significant byte of 2nd rank of \a u32.
1024#define MSB0(u32) MSB0W(u32) //!< Most significant byte of 1st rank of \a u32.
1025
1026#if defined(__ICCARM__)
1027#define SHORTENUM __packed
1028#elif defined(__GNUC__)
1029#define SHORTENUM __attribute__((packed))
1030#endif
1031
1032/* No operation */
1033#if defined(__ICCARM__)
1034#define nop() __no_operation()
1035#elif defined(__GNUC__)
1036#define nop() (__NOP())
1037#endif
1038
1039#define FLASH_DECLARE(x) const x
1040#define FLASH_EXTERN(x) extern const x
1041#define PGM_READ_BYTE(x) *(x)
1042#define PGM_READ_WORD(x) *(x)
1043#define MEMCPY_ENDIAN memcpy
1044#define PGM_READ_BLOCK(dst, src, len) memcpy((dst), (src), (len))
1045
1046/*Defines the Flash Storage for the request and response of MAC*/
1047#define CMD_ID_OCTET (0)
1048
1049/* Converting of values from CPU endian to little endian. */
1050#define CPU_ENDIAN_TO_LE16(x) (x)
1051#define CPU_ENDIAN_TO_LE32(x) (x)
1052#define CPU_ENDIAN_TO_LE64(x) (x)
1053
1054/* Converting of values from little endian to CPU endian. */
1055#define LE16_TO_CPU_ENDIAN(x) (x)
1056#define LE32_TO_CPU_ENDIAN(x) (x)
1057#define LE64_TO_CPU_ENDIAN(x) (x)
1058
1059/* Converting of constants from little endian to CPU endian. */
1060#define CLE16_TO_CPU_ENDIAN(x) (x)
1061#define CLE32_TO_CPU_ENDIAN(x) (x)
1062#define CLE64_TO_CPU_ENDIAN(x) (x)
1063
1064/* Converting of constants from CPU endian to little endian. */
1065#define CCPU_ENDIAN_TO_LE16(x) (x)
1066#define CCPU_ENDIAN_TO_LE32(x) (x)
1067#define CCPU_ENDIAN_TO_LE64(x) (x)
1068
1069#define ADDR_COPY_DST_SRC_16(dst, src) ((dst) = (src))
1070#define ADDR_COPY_DST_SRC_64(dst, src) ((dst) = (src))
1071
1072/**
1073 * @brief Converts a 64-Bit value into a 8 Byte array
1074 *
1075 * @param[in] value 64-Bit value
1076 * @param[out] data Pointer to the 8 Byte array to be updated with 64-Bit value
1077 * @ingroup apiPalApi
1078 */
1079static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
1080{
1081 uint8_t index = 0;
1082
1083 while (index < 8)
1084 {
1085 data[index++] = value & 0xFF;
1086 value = value >> 8;
1087 }
1088}
1089
1090/**
1091 * @brief Converts a 16-Bit value into a 2 Byte array
1092 *
1093 * @param[in] value 16-Bit value
1094 * @param[out] data Pointer to the 2 Byte array to be updated with 16-Bit value
1095 * @ingroup apiPalApi
1096 */
1097static inline void convert_16_bit_to_byte_array(uint16_t value, uint8_t *data)
1098{
1099 data[0] = value & 0xFF;
1100 data[1] = (value >> 8) & 0xFF;
1101}
1102
1103/* Converts a 16-Bit value into a 2 Byte array */
1104static inline void convert_spec_16_bit_to_byte_array(uint16_t value, uint8_t *data)
1105{
1106 data[0] = value & 0xFF;
1107 data[1] = (value >> 8) & 0xFF;
1108}
1109
1110/* Converts a 16-Bit value into a 2 Byte array */
1111static inline void convert_16_bit_to_byte_address(uint16_t value, uint8_t *data)
1112{
1113 data[0] = value & 0xFF;
1114 data[1] = (value >> 8) & 0xFF;
1115}
1116
1117/*
1118 * @brief Converts a 2 Byte array into a 16-Bit value
1119 *
1120 * @param data Specifies the pointer to the 2 Byte array
1121 *
1122 * @return 16-Bit value
1123 * @ingroup apiPalApi
1124 */
1125static inline uint16_t convert_byte_array_to_16_bit(uint8_t *data)
1126{
1127 return (data[0] | ((uint16_t)data[1] << 8));
1128}
1129
1130/* Converts a 4 Byte array into a 32-Bit value */
1131static inline uint32_t convert_byte_array_to_32_bit(uint8_t *data)
1132{
1133 union
1134 {
1135 uint32_t u32;
1136 uint8_t u8[4];
1137 } long_addr;
1138
1139 uint8_t index;
1140
1141 for (index = 0; index < 4; index++)
1142 {
1143 long_addr.u8[index] = *data++;
1144 }
1145
1146 return long_addr.u32;
1147}
1148
1149/**
1150 * @brief Converts a 8 Byte array into a 64-Bit value
1151 *
1152 * @param data Specifies the pointer to the 8 Byte array
1153 *
1154 * @return 64-Bit value
1155 * @ingroup apiPalApi
1156 */
1157static inline uint64_t convert_byte_array_to_64_bit(uint8_t *data)
1158{
1159 union
1160 {
1161 uint64_t u64;
1162 uint8_t u8[8];
1163 } long_addr;
1164
1165 uint8_t index;
1166
1167 for (index = 0; index < 8; index++)
1168 {
1169 long_addr.u8[index] = *data++;
1170 }
1171
1172 return long_addr.u64;
1173}
1174
1175/** @} */
1176
1177#endif /* UTILS_COMPILER_H_INCLUDED */
diff --git a/tmk_core/protocol/arm_atsam/usb/conf_usb.h b/tmk_core/protocol/arm_atsam/usb/conf_usb.h
new file mode 100644
index 000000000..8f0f47268
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/conf_usb.h
@@ -0,0 +1,163 @@
1/**
2 * \file
3 *
4 * \brief USB configuration file
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _CONF_USB_H_
48#define _CONF_USB_H_
49
50#include "compiler.h"
51#include "udi_device_conf.h"
52
53#define UDI_CDC_DEFAULT_RATE 115200
54#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
55#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
56#define UDI_CDC_DEFAULT_DATABITS 8
57
58//! Device definition (mandatory)
59#define USB_DEVICE_VENDOR_ID VENDOR_ID
60#define USB_DEVICE_PRODUCT_ID PRODUCT_ID
61#define USB_DEVICE_VERSION DEVICE_VER
62#define USB_DEVICE_POWER 500 // Consumption on Vbus line (mA)
63#define USB_DEVICE_ATTR (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
64// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
65// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
66// (USB_CONFIG_ATTR_SELF_POWERED)
67// (USB_CONFIG_ATTR_BUS_POWERED)
68
69//! USB Device string definitions (Optional)
70#define USB_DEVICE_MANUFACTURE_NAME MANUFACTURER
71#define USB_DEVICE_PRODUCT_NAME PRODUCT
72#define USB_DEVICE_SERIAL_NAME SERIAL_NUM
73
74//Comment out USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL to prevent ROM lookup of factory programmed serial number
75#define USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
76
77/**
78 * Device speeds support
79 * @{
80 */
81//! To define a Low speed device
82//#define USB_DEVICE_LOW_SPEED
83
84//! To authorize the High speed
85#if (UC3A3||UC3A4)
86//#define USB_DEVICE_HS_SUPPORT
87#elif (SAM3XA||SAM3U)
88//#define USB_DEVICE_HS_SUPPORT
89#endif
90//@}
91
92/**
93 * USB Device Callbacks definitions (Optional)
94 * @{
95 */
96#define UDC_VBUS_EVENT(b_vbus_high)
97#define UDC_SOF_EVENT() main_sof_action()
98#define UDC_SUSPEND_EVENT() main_suspend_action()
99#define UDC_RESUME_EVENT() main_resume_action()
100//! Mandatory when USB_DEVICE_ATTR authorizes remote wakeup feature
101#define UDC_REMOTEWAKEUP_ENABLE() main_remotewakeup_enable()
102#define UDC_REMOTEWAKEUP_DISABLE() main_remotewakeup_disable()
103//! When a extra string descriptor must be supported
104//! other than manufacturer, product and serial string
105// #define UDC_GET_EXTRA_STRING()
106//@}
107
108//@}
109
110
111/**
112 * USB Interface Configuration
113 * @{
114 */
115/**
116 * Configuration of HID Keyboard interface
117 * @{
118 */
119//! Interface callback definition
120#ifdef KBD
121#define UDI_HID_KBD_ENABLE_EXT() main_kbd_enable()
122#define UDI_HID_KBD_DISABLE_EXT() main_kbd_disable()
123//#define UDI_HID_KBD_CHANGE_LED(value) ui_kbd_led(value)
124#endif
125
126#ifdef NKRO
127#define UDI_HID_NKRO_ENABLE_EXT() main_nkro_enable()
128#define UDI_HID_NKRO_DISABLE_EXT() main_nkro_disable()
129//#define UDI_HID_NKRO_CHANGE_LED(value) ui_kbd_led(value)
130#endif
131
132#ifdef EXK
133#define UDI_HID_EXK_ENABLE_EXT() main_exk_enable()
134#define UDI_HID_EXK_DISABLE_EXT() main_exk_disable()
135#endif
136
137#ifdef MOU
138#define UDI_HID_MOU_ENABLE_EXT() main_mou_enable()
139#define UDI_HID_MOU_DISABLE_EXT() main_mou_disable()
140#endif
141
142#ifdef RAW
143#define UDI_HID_RAW_ENABLE_EXT() main_raw_enable()
144#define UDI_HID_RAW_DISABLE_EXT() main_raw_disable()
145#endif
146
147
148//@}
149//@}
150
151
152/**
153 * USB Device Driver Configuration
154 * @{
155 */
156//@}
157
158//! The includes of classes and other headers must be done at the end of this file to avoid compile error
159#include "udi_hid_kbd_conf.h"
160#include "usb_main.h"
161#include "ui.h"
162
163#endif // _CONF_USB_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/main_usb.c b/tmk_core/protocol/arm_atsam/usb/main_usb.c
new file mode 100644
index 000000000..e943cbcdc
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/main_usb.c
@@ -0,0 +1,118 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "samd51j18a.h"
19#include "conf_usb.h"
20#include "udd.h"
21
22uint8_t keyboard_protocol = 1;
23
24void main_suspend_action(void)
25{
26 ui_powerdown();
27}
28
29void main_resume_action(void)
30{
31 ui_wakeup();
32}
33
34void main_sof_action(void)
35{
36 ui_process(udd_get_frame_number());
37}
38
39void main_remotewakeup_enable(void)
40{
41 ui_wakeup_enable();
42}
43
44void main_remotewakeup_disable(void)
45{
46 ui_wakeup_disable();
47}
48
49#ifdef KBD
50volatile bool main_b_kbd_enable = false;
51bool main_kbd_enable(void)
52{
53 main_b_kbd_enable = true;
54 return true;
55}
56
57void main_kbd_disable(void)
58{
59 main_b_kbd_enable = false;
60}
61#endif
62
63#ifdef NKRO
64volatile bool main_b_nkro_enable = false;
65bool main_nkro_enable(void)
66{
67 main_b_nkro_enable = true;
68 return true;
69}
70
71void main_nkro_disable(void)
72{
73 main_b_nkro_enable = false;
74}
75#endif
76
77#ifdef EXK
78volatile bool main_b_exk_enable = false;
79bool main_exk_enable(void)
80{
81 main_b_exk_enable = true;
82 return true;
83}
84
85void main_exk_disable(void)
86{
87 main_b_exk_enable = false;
88}
89#endif
90
91#ifdef MOU
92volatile bool main_b_mou_enable = false;
93bool main_mou_enable(void)
94{
95 main_b_mou_enable = true;
96 return true;
97}
98
99void main_mou_disable(void)
100{
101 main_b_mou_enable = false;
102}
103#endif
104
105#ifdef RAW
106volatile bool main_b_raw_enable = false;
107bool main_raw_enable(void)
108{
109 main_b_raw_enable = true;
110 return true;
111}
112
113void main_raw_disable(void)
114{
115 main_b_raw_enable = false;
116}
117#endif
118
diff --git a/tmk_core/protocol/arm_atsam/usb/spfssf.c b/tmk_core/protocol/arm_atsam/usb/spfssf.c
new file mode 100644
index 000000000..449a8bb7d
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/spfssf.c
@@ -0,0 +1,268 @@
1#include "samd51j18a.h"
2#include "stdarg.h"
3#include "spfssf.h"
4#include "usb_util.h"
5
6int vspf(char *_Dest, const char *_Format, va_list va)
7{
8 //va_list va; //Variable argument list variable
9 char *d = _Dest; //Pointer to dest
10
11 //va_start(va,_Format); //Initialize the variable argument list
12 while (*_Format) //While not end of format string
13 {
14 if (*_Format == SPF_SPEC_START) //If current format string character is the specifier start character
15 {
16 _Format++; //Skip over the character
17 while (*_Format && *_Format <= 64) _Format++; //Forward past any options
18 if (*_Format == SPF_SPEC_START) *d++ = *_Format; //If the character is the specifier start character, output the character and advance dest
19 else if (*_Format == SPF_SPEC_LONG) //If the character is the long type
20 {
21 _Format++; //Skip over the character
22 if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
23 {
24 int64_t buf = va_arg(va,int64_t); //Get the next value from the va list
25 //if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
26 //spf_uint2str_32_3t(&d,buf,32); //Perform the conversion
27 d += UTIL_ltoa_radix(buf, d, 10);
28 }
29 else if (*_Format == SPF_SPEC_UNSIGNED) //If the character is the unsigned type
30 {
31 uint64_t num = va_arg(va,uint64_t); //Get the next value from the va list
32 //spf_uint2str_32_3t(&d,num,32); //Perform the conversion
33 d += UTIL_ltoa_radix(num, d, 10);
34 }
35 else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the unsigned type
36 {
37 uint64_t buf = va_arg(va,uint64_t); //Get the next value from the va list
38 //spf_uint2hex_32(&d,(unsigned long) buf);
39 d += UTIL_ltoa_radix(buf, d, 16);
40 }
41 else //If the character was not a known type
42 {
43 *d++ = SPF_SPEC_START; //Output the start specifier
44 *d++ = SPF_SPEC_LONG; //Output the long type
45 *d++ = *_Format; //Output the unknown type
46 }
47 }
48 else if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
49 {
50 int buf = va_arg(va,int); //Get the next value from the va list
51 //if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
52 //spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
53 d += UTIL_itoa(buf, d);
54 }
55 else if (*_Format == SPF_SPEC_INT) //If the character is the integer type
56 {
57 int buf = va_arg(va,int); //Get the next value from the va list
58 //if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and inverted number
59 //spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
60 d += UTIL_itoa(buf, d);
61 }
62 else if (*_Format == SPF_SPEC_UINT) //If the character is the unsigned integer type
63 {
64 int buf = va_arg(va,int); //Get the next value from the va list
65 //spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
66 d += UTIL_utoa(buf, d);
67 }
68 else if (*_Format == SPF_SPEC_STRING) //If the character is the string type
69 {
70 char *buf = va_arg(va,char*); //Get the next value from the va list
71 while (*buf) *d++ = *buf++; //Perform the conversion (simply output characters and adcance pointers)
72 }
73 else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the short type
74 {
75 int buf = va_arg(va,unsigned int); //Get the next value from the va list
76 //spf_uint2hex_32(&d,(unsigned long) buf); //Perform the conversion
77 d += UTIL_utoa(buf, d);
78 }
79 else //If the character type is unknown
80 {
81 *d++ = SPF_SPEC_START; //Output the start specifier
82 *d++ = *_Format; //Output the unknown type
83 }
84 }
85 else *d++ = *_Format; //If the character is unknown, output it to dest and advance dest
86 _Format++; //Advance the format buffer pointer to next character
87 }
88 //va_end(va); //End the variable argument list
89
90 *d = '\0'; //Cap off the destination string with a zero
91
92 return d - _Dest; //Return the length of the destintion buffer
93}
94
95int spf(char *_Dest, const char *_Format, ...)
96{
97 va_list va; //Variable argument list variable
98 int result;
99
100 va_start(va,_Format); //Initialize the variable argument list
101 result = vspf(_Dest, _Format, va);
102 va_end(va);
103 return result;
104}
105
106//sscanf string to number (integer types)
107int64_t ssf_ston(const char **_Src, uint32_t count, uint32_t *conv_count)
108{
109 int64_t value = 0; //Return value accumulator
110 uint32_t counter=count; //Counter to keep track of numbers converted
111 const char* p; //Pointer to first non space character
112
113 while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
114
115 p = (*_Src); //Set pointer to first non space character
116 if (*p == '+' || *p == '-') (*_Src)++; //Skip over sign if any
117 while (*(*_Src) >= ASCII_NUM_START &&
118 *(*_Src) <= ASCII_NUM_END &&
119 counter) //While the source character is a digit and counter is not zero
120 {
121 value *= 10; //Multiply result by 10 to make room for next 1's place number
122 value += *(*_Src)++ - ASCII_NUM_START; //Add source number to value
123 counter--; //Decrement counter
124 }
125 if (counter - count == 0) return 0; //If no number conversion were performed, return 0
126 if (*p == '-') value = -value; //If the number given was negative, make the result negative
127
128 if (conv_count) (*conv_count)++; //Increment the converted count
129 return value; //Return the value
130}
131
132uint64_t ssf_hton(const char **_Src, uint32_t count,uint32_t *conv_count)
133{
134 int64_t value=0; //Return value accumulator
135 uint32_t counter=count; //Counter to keep track of numbers converted
136 //const char* p; //Pointer to first non space character
137 char c;
138
139 while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
140
141 //p = (*_Src); //Set pointer to first non space character
142
143 while (counter)
144 {
145 c = *(*_Src)++;
146 if (c >= 'a' && c <= 'f') c -= ('a'-'A'); //toupper
147 if (c < '0' || (c > '9' && c < 'A') || c > 'F') break;
148 value *= 16; //Multiply result by 10 to make room for next 1's place number
149 c = c - '0';
150 if (c > 9) c -= 7;
151 value += c; //Add source number to value
152 counter--; //Decrement counter
153 }
154
155 if (counter - count == 0) return 0; //If no number conversion were performed, return 0
156 //if (*p == '-') value = -value; //If the number given was negative, make the result negative
157
158 if (conv_count) (*conv_count)++; //Increment the converted count
159 return value;
160}
161
162//sscanf
163int ssf(const char *_Src, const char *_Format, ...)
164{
165 va_list va; //Variable argument list variable
166 unsigned char looking_for=0; //Static char specified in format to be found in source
167 uint32_t conv_count=0; //Count of conversions made
168
169 va_start(va,_Format); //Initialize the variable argument list
170 while (*_Format) //While the format string has not been fully read
171 {
172 if (looking_for != 0) //If we are looking for a matching character in the source string
173 {
174 while (*_Src != looking_for && *_Src) _Src++; //While the character is not found in the source string and not the end of the source
175 // string, increment the pointer position
176 if (*_Src == looking_for) _Src++; //If the character was found, step over it
177 else break; //Else the end was reached and the scan is now invalid (Could not find static character)
178 looking_for = 0; //Clear the looking for character
179 }
180 if (*_Format == SSF_SPEC_START) //If the current format character is the specifier start character
181 {
182 _Format++; //Step over the specifier start character
183 if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
184 {
185 int *value=va_arg(va,int*); //User given destination address
186 //*value = (int)ssf_ston(&_Src,5,&conv_count); //Run conversion
187 *value = (int)ssf_ston(&_Src,10,&conv_count); //Run conversion
188 }
189 else if (*_Format == SSF_SPEC_LONG) //If the long specifier type is found
190 {
191 _Format++; //Skip over the specifier type
192 if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
193 {
194 int64_t *value=va_arg(va,int64_t*); //User given destination address
195 //*value = (int64_t)ssf_ston(&_Src,10,&conv_count); //Run conversion
196 *value = (int64_t)ssf_ston(&_Src,19,&conv_count); //Run conversion
197 }
198 else if (*_Format == SSF_SPEC_UHINT) //If the decimal specifier type is found
199 {
200 uint64_t *value=va_arg(va,uint64_t *); //User given destination address
201 //*value = (uint64_t int)ssf_hton(&_Src,12,&conv_count); //Run conversion
202 *value = (uint64_t)ssf_hton(&_Src,16,&conv_count); //Run conversion
203 }
204 }
205 else if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
206 {
207 _Format++; //Skip over the specifier type
208 if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
209 {
210 _Format++; //Skip over the specifier type
211 if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
212 {
213 unsigned char *value=va_arg(va,unsigned char*); //User given destination address
214 //*value = (unsigned char)ssf_ston(&_Src,3,&conv_count); //Run conversion
215 *value = (unsigned char)ssf_ston(&_Src,5,&conv_count); //Run conversion
216 }
217 }
218 }
219 else if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
220 {
221 char *value=va_arg(va,char*); //User given destination address, max chars read pointer
222 while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
223 while (*_Src != SSF_SKIP_SPACE && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
224 *value = 0; //Cap off the string pointer with zero
225 conv_count++; //Increment the converted count
226 }
227 else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
228 {
229 char *value=va_arg(va,char*); //User given destination address, max chars read pointer
230 while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
231 while (*_Src != SSF_DELIM_COMMA && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
232 *value = 0; //Cap off the string pointer with zero
233 conv_count++; //Increment the converted count
234 }
235 else if (*_Format >= ASCII_NUM_START && *_Format <= ASCII_NUM_END)
236 {
237 uint32_t len = (uint32_t)ssf_ston(&_Format,3,NULL); //Convert the given length
238 if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
239 {
240 char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
241 while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
242 e = (char*)_Src+len; //Set a maximum length pointer location
243 while (*_Src != SSF_SKIP_SPACE && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
244 *value = 0; //Cap off the string pointer with zero
245 conv_count++; //Increment the converted count
246 }
247 else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
248 {
249 char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
250 while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
251 e = (char*)_Src+len; //Set a maximum length pointer location
252 while (*_Src != SSF_DELIM_COMMA && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
253 *value = 0; //Cap off the string pointer with zero
254 conv_count++; //Increment the converted count
255 }
256 }
257 else if (*_Format == SSF_SPEC_START) looking_for = *_Format; //If another start specifier character is found, output a specifier character
258 else break; //Scan is now invalid (Uknown type specified)
259 }
260 else if (*_Format == SSF_SKIP_SPACE) { } //If a space is found, ignore it
261 else looking_for = *_Format; //If any other character is found, it is static and should be found in src as well
262 _Format++; //Skip over current format character
263 }
264
265 va_end(va); //End the variable argument list
266 return conv_count; //Return the number of conversions made
267}
268
diff --git a/tmk_core/protocol/arm_atsam/usb/spfssf.h b/tmk_core/protocol/arm_atsam/usb/spfssf.h
new file mode 100644
index 000000000..337a904df
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/spfssf.h
@@ -0,0 +1,57 @@
1#ifndef ____spfssf_h
2#define ____spfssf_h
3
4#include <stdarg.h>
5
6#define sprintf spf
7#define sscanf ssf
8
9#define SIZEOF_OFFSET 1
10
11#ifndef NULL
12#define NULL 0
13#endif
14
15#define SPF_NONE 0
16
17#define SPF_SPEC_START 37 //%
18#define SPF_SPEC_DECIMAL 100 //d 16bit dec signed (-32767 to 32767) DONE same as i
19#define SPF_SPEC_INT 105 //i 16bit dec signed (-32767 to 32767) DONE same as d
20#define SPF_SPEC_UINT 117 //u 16bit dec unsigned (0 to 65535) DONE
21#define SPF_SPEC_STRING 115 //s variable length (abcd...) DONE
22#define SPF_SPEC_UHINT 120 //x 16bit hex lwrc (7fa) DONE
23#define SPF_SPEC_UHINT_UP 88 //x 16bit hex lwrc (7fa) DONE
24#define SPF_SPEC_LONG 108 //l start of either ld or lu DONE
25#define SPF_SPEC_DECIMAL 100 //ld 32bit dec signed (-2147483647 to 2147483647) DONE
26#define SPF_SPEC_UNSIGNED 117 //lu 32bit dec unsigned (0 to 4294967295) DONE
27#define SPF_SPEC_UHINT 120 //lx 32bit hex unsigned (0 to ffffffff) DONE
28
29#define SSF_SPEC_START 37 //%
30#define SSF_SPEC_SHORTINT 104 //h 8bit dec signed (-127 to 127) DONE
31#define SSF_LEN_SHORTINT 3 //hhd
32#define SSF_SPEC_DECIMAL 100 //d 16bit dec signed (-32767 to 32767) DONE
33#define SSF_LEN_DECIMAL 5 //32767
34#define SSF_SPEC_INT 105 //i 16bit dec signed (-32767 to 32767) DONE
35#define SSF_LEN_INT 5 //32767
36#define SSF_SPEC_LONG 108 //l start of either ld or lu DONE
37#define SSF_SPEC_DECIMAL 100 //ld 32bit dec signed (-2147483647 to 2147483647) DONE
38#define SSF_SPEC_UHINT 120 //lx 32bit hex unsigned DONE
39#define SSF_LEN_LDECIMAL 10 //2147483647
40#define SSF_SPEC_STRING 115 //s variable length (abcd...) DONE
41#define SSF_SKIP_SPACE 32 //space
42
43#define SSF_SPEC_VERSION 118 //v collect to comma delimiter - special
44#define SSF_DELIM_COMMA 44 //,
45
46#define ASCII_NUM_START 48 //0
47#define ASCII_NUM_END 58 //9
48
49#define T_UINT32_0_LIMIT 14
50#define T_UINT32_1_LIMIT 27
51
52int vspf(char *_Dest, const char *_Format, va_list va);
53int spf(char *_Dest, const char *_Format, ...);
54int ssf(const char *_Src, const char *_Format, ...);
55
56#endif //____spfssf_h
57
diff --git a/tmk_core/protocol/arm_atsam/usb/status_codes.h b/tmk_core/protocol/arm_atsam/usb/status_codes.h
new file mode 100644
index 000000000..f56d2faed
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/status_codes.h
@@ -0,0 +1,158 @@
1/**
2 * \file
3 *
4 * \brief Status code definitions.
5 *
6 * This file defines various status codes returned by functions,
7 * indicating success or failure as well as what kind of failure.
8 *
9 * Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
10 *
11 * \asf_license_start
12 *
13 * \page License
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright notice,
19 * this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 *
25 * 3. The name of Atmel may not be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * 4. This software may only be redistributed and used in connection with an
29 * Atmel microcontroller product.
30 *
31 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
34 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
35 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
42 *
43 * \asf_license_stop
44 *
45 */
46/*
47 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
48 */
49
50#ifndef STATUS_CODES_H_INCLUDED
51#define STATUS_CODES_H_INCLUDED
52
53#include <stdint.h>
54
55/**
56 * \defgroup group_sam0_utils_status_codes Status Codes
57 *
58 * \ingroup group_sam0_utils
59 *
60 * @{
61 */
62
63/** Mask to retrieve the error category of a status code. */
64#define STATUS_CATEGORY_MASK 0xF0
65
66/** Mask to retrieve the error code within the category of a status code. */
67#define STATUS_ERROR_MASK 0x0F
68
69/** Status code error categories. */
70enum status_categories {
71 STATUS_CATEGORY_OK = 0x00,
72 STATUS_CATEGORY_COMMON = 0x10,
73 STATUS_CATEGORY_ANALOG = 0x30,
74 STATUS_CATEGORY_COM = 0x40,
75 STATUS_CATEGORY_IO = 0x50,
76};
77
78/**
79 * Status code that may be returned by shell commands and protocol
80 * implementations.
81 *
82 * \note Any change to these status codes and the corresponding
83 * message strings is strictly forbidden. New codes can be added,
84 * however, but make sure that any message string tables are updated
85 * at the same time.
86 */
87enum status_code {
88 STATUS_OK = STATUS_CATEGORY_OK | 0x00,
89 STATUS_VALID_DATA = STATUS_CATEGORY_OK | 0x01,
90 STATUS_NO_CHANGE = STATUS_CATEGORY_OK | 0x02,
91 STATUS_ABORTED = STATUS_CATEGORY_OK | 0x04,
92 STATUS_BUSY = STATUS_CATEGORY_OK | 0x05,
93 STATUS_SUSPEND = STATUS_CATEGORY_OK | 0x06,
94
95 STATUS_ERR_IO = STATUS_CATEGORY_COMMON | 0x00,
96 STATUS_ERR_REQ_FLUSHED = STATUS_CATEGORY_COMMON | 0x01,
97 STATUS_ERR_TIMEOUT = STATUS_CATEGORY_COMMON | 0x02,
98 STATUS_ERR_BAD_DATA = STATUS_CATEGORY_COMMON | 0x03,
99 STATUS_ERR_NOT_FOUND = STATUS_CATEGORY_COMMON | 0x04,
100 STATUS_ERR_UNSUPPORTED_DEV = STATUS_CATEGORY_COMMON | 0x05,
101 STATUS_ERR_NO_MEMORY = STATUS_CATEGORY_COMMON | 0x06,
102 STATUS_ERR_INVALID_ARG = STATUS_CATEGORY_COMMON | 0x07,
103 STATUS_ERR_BAD_ADDRESS = STATUS_CATEGORY_COMMON | 0x08,
104 STATUS_ERR_BAD_FORMAT = STATUS_CATEGORY_COMMON | 0x0A,
105 STATUS_ERR_BAD_FRQ = STATUS_CATEGORY_COMMON | 0x0B,
106 STATUS_ERR_DENIED = STATUS_CATEGORY_COMMON | 0x0c,
107 STATUS_ERR_ALREADY_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0d,
108 STATUS_ERR_OVERFLOW = STATUS_CATEGORY_COMMON | 0x0e,
109 STATUS_ERR_NOT_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0f,
110
111 STATUS_ERR_SAMPLERATE_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x00,
112 STATUS_ERR_RESOLUTION_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x01,
113
114 STATUS_ERR_BAUDRATE_UNAVAILABLE = STATUS_CATEGORY_COM | 0x00,
115 STATUS_ERR_PACKET_COLLISION = STATUS_CATEGORY_COM | 0x01,
116 STATUS_ERR_PROTOCOL = STATUS_CATEGORY_COM | 0x02,
117
118 STATUS_ERR_PIN_MUX_INVALID = STATUS_CATEGORY_IO | 0x00,
119};
120typedef enum status_code status_code_genare_t;
121
122/**
123 Status codes used by MAC stack.
124 */
125enum status_code_wireless {
126 //STATUS_OK = 0, //!< Success
127 ERR_IO_ERROR = -1, //!< I/O error
128 ERR_FLUSHED = -2, //!< Request flushed from queue
129 ERR_TIMEOUT = -3, //!< Operation timed out
130 ERR_BAD_DATA = -4, //!< Data integrity check failed
131 ERR_PROTOCOL = -5, //!< Protocol error
132 ERR_UNSUPPORTED_DEV = -6, //!< Unsupported device
133 ERR_NO_MEMORY = -7, //!< Insufficient memory
134 ERR_INVALID_ARG = -8, //!< Invalid argument
135 ERR_BAD_ADDRESS = -9, //!< Bad address
136 ERR_BUSY = -10, //!< Resource is busy
137 ERR_BAD_FORMAT = -11, //!< Data format not recognized
138 ERR_NO_TIMER = -12, //!< No timer available
139 ERR_TIMER_ALREADY_RUNNING = -13, //!< Timer already running
140 ERR_TIMER_NOT_RUNNING = -14, //!< Timer not running
141
142 /**
143 * \brief Operation in progress
144 *
145 * This status code is for driver-internal use when an operation
146 * is currently being performed.
147 *
148 * \note Drivers should never return this status code to any
149 * callers. It is strictly for internal use.
150 */
151 OPERATION_IN_PROGRESS = -128,
152};
153
154typedef enum status_code_wireless status_code_t;
155
156/** @} */
157
158#endif /* STATUS_CODES_H_INCLUDED */
diff --git a/tmk_core/protocol/arm_atsam/usb/udc.c b/tmk_core/protocol/arm_atsam/usb/udc.c
new file mode 100644
index 000000000..12444d305
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udc.c
@@ -0,0 +1,1164 @@
1/**
2 * \file
3 *
4 * \brief USB Device Controller (UDC)
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#include "conf_usb.h"
48#include "usb_protocol.h"
49#include "udd.h"
50#include "udc_desc.h"
51#include "udi_device_conf.h"
52#include "udi.h"
53#include "udc.h"
54#include "md_bootloader.h"
55
56/**
57 * \ingroup udc_group
58 * \defgroup udc_group_interne Implementation of UDC
59 *
60 * Internal implementation
61 * @{
62 */
63
64//! \name Internal variables to manage the USB device
65//! @{
66
67//! Device status state (see enum usb_device_status in usb_protocol.h)
68static le16_t udc_device_status;
69
70COMPILER_WORD_ALIGNED
71//! Device interface setting value
72static uint8_t udc_iface_setting = 0;
73
74//! Device Configuration number selected by the USB host
75COMPILER_WORD_ALIGNED
76static uint8_t udc_num_configuration = 0;
77
78//! Pointer on the selected speed device configuration
79static udc_config_speed_t UDC_DESC_STORAGE *udc_ptr_conf;
80
81//! Pointer on interface descriptor used by SETUP request.
82static usb_iface_desc_t UDC_DESC_STORAGE *udc_ptr_iface;
83
84//! @}
85
86
87//! \name Internal structure to store the USB device main strings
88//! @{
89
90/**
91 * \brief Language ID of USB device (US ID by default)
92 */
93COMPILER_WORD_ALIGNED
94static UDC_DESC_STORAGE usb_str_lgid_desc_t udc_string_desc_languageid = {
95 .desc.bLength = sizeof(usb_str_lgid_desc_t),
96 .desc.bDescriptorType = USB_DT_STRING,
97 .string = {LE16(USB_LANGID_EN_US)}
98};
99
100/**
101 * \brief USB device manufacture name storage
102 * String is allocated only if USB_DEVICE_MANUFACTURE_NAME is declared
103 * by usb application configuration
104 */
105#ifdef USB_DEVICE_MANUFACTURE_NAME
106static uint8_t udc_string_manufacturer_name[] = USB_DEVICE_MANUFACTURE_NAME;
107#define USB_DEVICE_MANUFACTURE_NAME_SIZE (sizeof(udc_string_manufacturer_name)-1)
108#else
109#define USB_DEVICE_MANUFACTURE_NAME_SIZE 0
110#endif
111
112/**
113 * \brief USB device product name storage
114 * String is allocated only if USB_DEVICE_PRODUCT_NAME is declared
115 * by usb application configuration
116 */
117#ifdef USB_DEVICE_PRODUCT_NAME
118static uint8_t udc_string_product_name[] = USB_DEVICE_PRODUCT_NAME;
119#define USB_DEVICE_PRODUCT_NAME_SIZE (sizeof(udc_string_product_name)-1)
120#else
121#define USB_DEVICE_PRODUCT_NAME_SIZE 0
122#endif
123
124#if defined USB_DEVICE_SERIAL_NAME
125#define USB_DEVICE_SERIAL_NAME_SIZE (sizeof(USB_DEVICE_SERIAL_NAME)-1)
126#else
127#define USB_DEVICE_SERIAL_NAME_SIZE 0
128#endif
129
130uint8_t usb_device_serial_name_size = 0;
131#if defined USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
132uint8_t bootloader_serial_number[BOOTLOADER_SERIAL_MAX_SIZE+1]="";
133#endif
134static const uint8_t *udc_get_string_serial_name(void)
135{
136#if defined USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
137 uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
138 uint32_t serial_address = *(uint32_t *)serial_ptrloc; //Address of bootloader's serial number if available
139
140 if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
141 {
142 if ((serial_address & 0xFF) % 4 == 0) //Check alignment
143 {
144 uint16_t *serial_use = (uint16_t *)(serial_address); //Point to address of string in rom
145 uint8_t serial_length = 0;
146
147 while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
148 serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
149 {
150 bootloader_serial_number[serial_length] = *(serial_use + serial_length) & 0xFF;
151 serial_length++;
152 }
153 bootloader_serial_number[serial_length] = 0;
154
155 usb_device_serial_name_size = serial_length;
156
157 return bootloader_serial_number; //Use serial programmed into bootloader rom
158 }
159 }
160#endif
161
162 usb_device_serial_name_size = USB_DEVICE_SERIAL_NAME_SIZE;
163
164#if defined USB_DEVICE_SERIAL_NAME
165 return (const uint8_t *)USB_DEVICE_SERIAL_NAME; //Use serial supplied by keyboard's config.h
166#else
167 return 0; //No serial supplied
168#endif
169}
170
171/**
172 * \brief USB device string descriptor
173 * Structure used to transfer ASCII strings to USB String descriptor structure.
174 */
175#ifndef BOOTLOADER_SERIAL_MAX_SIZE
176#define BOOTLOADER_SERIAL_MAX_SIZE 0
177#endif //BOOTLOADER_SERIAL_MAX_SIZE
178struct udc_string_desc_t {
179 usb_str_desc_t header;
180 le16_t string[Max(Max(Max(USB_DEVICE_MANUFACTURE_NAME_SIZE, \
181 USB_DEVICE_PRODUCT_NAME_SIZE), USB_DEVICE_SERIAL_NAME_SIZE), \
182 BOOTLOADER_SERIAL_MAX_SIZE)];
183};
184COMPILER_WORD_ALIGNED
185static UDC_DESC_STORAGE struct udc_string_desc_t udc_string_desc = {
186 .header.bDescriptorType = USB_DT_STRING
187};
188//! @}
189
190usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void)
191{
192 return udc_ptr_iface;
193}
194
195/**
196 * \brief Returns a value to check the end of USB Configuration descriptor
197 *
198 * \return address after the last byte of USB Configuration descriptor
199 */
200static usb_conf_desc_t UDC_DESC_STORAGE *udc_get_eof_conf(void)
201{
202 return (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *)
203 udc_ptr_conf->desc +
204 le16_to_cpu(udc_ptr_conf->desc->wTotalLength));
205}
206
207#if (0!=USB_DEVICE_MAX_EP)
208/**
209 * \brief Search specific descriptor in global interface descriptor
210 *
211 * \param desc Address of interface descriptor
212 * or previous specific descriptor found
213 * \param desc_id Descriptor ID to search
214 *
215 * \return address of specific descriptor found
216 * \return NULL if it is the end of global interface descriptor
217 */
218static usb_conf_desc_t UDC_DESC_STORAGE *udc_next_desc_in_iface(usb_conf_desc_t
219 UDC_DESC_STORAGE * desc, uint8_t desc_id)
220{
221 usb_conf_desc_t UDC_DESC_STORAGE *ptr_eof_desc;
222
223 ptr_eof_desc = udc_get_eof_conf();
224 // Go to next descriptor
225 desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc +
226 desc->bLength);
227 // Check the end of configuration descriptor
228 while (ptr_eof_desc > desc) {
229 // If new interface descriptor is found,
230 // then it is the end of the current global interface descriptor
231 if (USB_DT_INTERFACE == desc->bDescriptorType) {
232 break; // End of global interface descriptor
233 }
234 if (desc_id == desc->bDescriptorType) {
235 return desc; // Specific descriptor found
236 }
237 // Go to next descriptor
238 desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc +
239 desc->bLength);
240 }
241 return NULL; // No specific descriptor found
242}
243#endif
244
245/**
246 * \brief Search an interface descriptor
247 * This routine updates the internal pointer udc_ptr_iface.
248 *
249 * \param iface_num Interface number to find in Configuration Descriptor
250 * \param setting_num Setting number of interface to find
251 *
252 * \return 1 if found or 0 if not found
253 */
254static bool udc_update_iface_desc(uint8_t iface_num, uint8_t setting_num)
255{
256 usb_conf_desc_t UDC_DESC_STORAGE *ptr_end_desc;
257
258 if (0 == udc_num_configuration) {
259 return false;
260 }
261
262 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
263 return false;
264 }
265
266 // Start at the beginning of configuration descriptor
267 udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *)
268 udc_ptr_conf->desc;
269
270 // Check the end of configuration descriptor
271 ptr_end_desc = udc_get_eof_conf();
272 while (ptr_end_desc >
273 (UDC_DESC_STORAGE usb_conf_desc_t *) udc_ptr_iface) {
274 if (USB_DT_INTERFACE == udc_ptr_iface->bDescriptorType) {
275 // A interface descriptor is found
276 // Check interface and alternate setting number
277 if ((iface_num == udc_ptr_iface->bInterfaceNumber) &&
278 (setting_num ==
279 udc_ptr_iface->bAlternateSetting)) {
280 return true; // Interface found
281 }
282 }
283 // Go to next descriptor
284 udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *) (
285 (uint8_t *) udc_ptr_iface +
286 udc_ptr_iface->bLength);
287 }
288 return false; // Interface not found
289}
290
291/**
292 * \brief Disables an usb device interface (UDI)
293 * This routine call the UDI corresponding to interface number
294 *
295 * \param iface_num Interface number to disable
296 *
297 * \return 1 if it is done or 0 if interface is not found
298 */
299static bool udc_iface_disable(uint8_t iface_num)
300{
301 udi_api_t UDC_DESC_STORAGE *udi_api;
302
303 // Select first alternate setting of the interface
304 // to update udc_ptr_iface before call iface->getsetting()
305 if (!udc_update_iface_desc(iface_num, 0)) {
306 return false;
307 }
308
309 // Select the interface with the current alternate setting
310 udi_api = udc_ptr_conf->udi_apis[iface_num];
311
312#if (0!=USB_DEVICE_MAX_EP)
313 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
314 return false;
315 }
316
317 // Start at the beginning of interface descriptor
318 {
319 usb_ep_desc_t UDC_DESC_STORAGE *ep_desc;
320 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface;
321 while (1) {
322 // Search Endpoint descriptor included in global interface descriptor
323 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *)
324 udc_next_desc_in_iface((UDC_DESC_STORAGE
325 usb_conf_desc_t *)
326 ep_desc, USB_DT_ENDPOINT);
327 if (NULL == ep_desc) {
328 break;
329 }
330 // Free the endpoint used by the interface
331 udd_ep_free(ep_desc->bEndpointAddress);
332 }
333 }
334#endif
335
336 // Disable interface
337 udi_api->disable();
338 return true;
339}
340
341/**
342 * \brief Enables an usb device interface (UDI)
343 * This routine calls the UDI corresponding
344 * to the interface and setting number.
345 *
346 * \param iface_num Interface number to enable
347 * \param setting_num Setting number to enable
348 *
349 * \return 1 if it is done or 0 if interface is not found
350 */
351static bool udc_iface_enable(uint8_t iface_num, uint8_t setting_num)
352{
353 // Select the interface descriptor
354 if (!udc_update_iface_desc(iface_num, setting_num)) {
355 return false;
356 }
357
358#if (0!=USB_DEVICE_MAX_EP)
359 usb_ep_desc_t UDC_DESC_STORAGE *ep_desc;
360
361 // Start at the beginning of the global interface descriptor
362 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface;
363 while (1) {
364 // Search Endpoint descriptor included in the global interface descriptor
365 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *)
366 udc_next_desc_in_iface((UDC_DESC_STORAGE
367 usb_conf_desc_t *) ep_desc,
368 USB_DT_ENDPOINT);
369 if (NULL == ep_desc)
370 break;
371 // Alloc the endpoint used by the interface
372 if (!udd_ep_alloc(ep_desc->bEndpointAddress,
373 ep_desc->bmAttributes,
374 le16_to_cpu
375 (ep_desc->wMaxPacketSize))) {
376 return false;
377 }
378 }
379#endif
380 // Enable the interface
381 return udc_ptr_conf->udi_apis[iface_num]->enable();
382}
383
384/*! \brief Start the USB Device stack
385 */
386void udc_start(void)
387{
388 udd_enable();
389}
390
391/*! \brief Stop the USB Device stack
392 */
393void udc_stop(void)
394{
395 udd_disable();
396 udc_reset();
397}
398
399/**
400 * \brief Reset the current configuration of the USB device,
401 * This routines can be called by UDD when a RESET on the USB line occurs.
402 */
403void udc_reset(void)
404{
405 uint8_t iface_num;
406
407 if (udc_num_configuration) {
408 for (iface_num = 0;
409 iface_num < udc_ptr_conf->desc->bNumInterfaces;
410 iface_num++) {
411 udc_iface_disable(iface_num);
412 }
413 }
414 udc_num_configuration = 0;
415#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
416 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
417 if (CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP) & udc_device_status) {
418 // Remote wakeup is enabled then disable it
419 UDC_REMOTEWAKEUP_DISABLE();
420 }
421#endif
422 udc_device_status =
423#if (USB_DEVICE_ATTR & USB_CONFIG_ATTR_SELF_POWERED)
424 CPU_TO_LE16(USB_DEV_STATUS_SELF_POWERED);
425#else
426 CPU_TO_LE16(USB_DEV_STATUS_BUS_POWERED);
427#endif
428}
429
430void udc_sof_notify(void)
431{
432 uint8_t iface_num;
433
434 if (udc_num_configuration) {
435 for (iface_num = 0;
436 iface_num < udc_ptr_conf->desc->bNumInterfaces;
437 iface_num++) {
438 if (udc_ptr_conf->udi_apis[iface_num]->sof_notify != NULL) {
439 udc_ptr_conf->udi_apis[iface_num]->sof_notify();
440 }
441 }
442 }
443}
444
445/**
446 * \brief Standard device request to get device status
447 *
448 * \return true if success
449 */
450static bool udc_req_std_dev_get_status(void)
451{
452 if (udd_g_ctrlreq.req.wLength != sizeof(udc_device_status)) {
453 return false;
454 }
455
456 udd_set_setup_payload( (uint8_t *) & udc_device_status,
457 sizeof(udc_device_status));
458 return true;
459}
460
461#if (0!=USB_DEVICE_MAX_EP)
462/**
463 * \brief Standard endpoint request to get endpoint status
464 *
465 * \return true if success
466 */
467static bool udc_req_std_ep_get_status(void)
468{
469 static le16_t udc_ep_status;
470
471 if (udd_g_ctrlreq.req.wLength != sizeof(udc_ep_status)) {
472 return false;
473 }
474
475 udc_ep_status = udd_ep_is_halted(udd_g_ctrlreq.req.
476 wIndex & 0xFF) ? CPU_TO_LE16(USB_EP_STATUS_HALTED) : 0;
477
478 udd_set_setup_payload( (uint8_t *) & udc_ep_status,
479 sizeof(udc_ep_status));
480 return true;
481}
482#endif
483
484/**
485 * \brief Standard device request to change device status
486 *
487 * \return true if success
488 */
489static bool udc_req_std_dev_clear_feature(void)
490{
491 if (udd_g_ctrlreq.req.wLength) {
492 return false;
493 }
494
495 if (udd_g_ctrlreq.req.wValue == USB_DEV_FEATURE_REMOTE_WAKEUP) {
496 udc_device_status &= CPU_TO_LE16(~(uint32_t)USB_DEV_STATUS_REMOTEWAKEUP);
497#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
498 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
499 UDC_REMOTEWAKEUP_DISABLE();
500#endif
501 return true;
502 }
503 return false;
504}
505
506#if (0!=USB_DEVICE_MAX_EP)
507/**
508 * \brief Standard endpoint request to clear endpoint feature
509 *
510 * \return true if success
511 */
512static bool udc_req_std_ep_clear_feature(void)
513{
514 if (udd_g_ctrlreq.req.wLength) {
515 return false;
516 }
517
518 if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) {
519 return udd_ep_clear_halt(udd_g_ctrlreq.req.wIndex & 0xFF);
520 }
521 return false;
522}
523#endif
524
525/**
526 * \brief Standard device request to set a feature
527 *
528 * \return true if success
529 */
530static bool udc_req_std_dev_set_feature(void)
531{
532 if (udd_g_ctrlreq.req.wLength) {
533 return false;
534 }
535
536 switch (udd_g_ctrlreq.req.wValue) {
537
538 case USB_DEV_FEATURE_REMOTE_WAKEUP:
539#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
540 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
541 udc_device_status |= CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP);
542 UDC_REMOTEWAKEUP_ENABLE();
543 return true;
544#else
545 return false;
546#endif
547
548#ifdef USB_DEVICE_HS_SUPPORT
549 case USB_DEV_FEATURE_TEST_MODE:
550 if (!udd_is_high_speed()) {
551 break;
552 }
553 if (udd_g_ctrlreq.req.wIndex & 0xff) {
554 break;
555 }
556 // Unconfigure the device, terminating all ongoing requests
557 udc_reset();
558 switch ((udd_g_ctrlreq.req.wIndex >> 8) & 0xFF) {
559 case USB_DEV_TEST_MODE_J:
560 udd_g_ctrlreq.callback = udd_test_mode_j;
561 return true;
562
563 case USB_DEV_TEST_MODE_K:
564 udd_g_ctrlreq.callback = udd_test_mode_k;
565 return true;
566
567 case USB_DEV_TEST_MODE_SE0_NAK:
568 udd_g_ctrlreq.callback = udd_test_mode_se0_nak;
569 return true;
570
571 case USB_DEV_TEST_MODE_PACKET:
572 udd_g_ctrlreq.callback = udd_test_mode_packet;
573 return true;
574
575 case USB_DEV_TEST_MODE_FORCE_ENABLE: // Only for downstream facing hub ports
576 default:
577 break;
578 }
579 break;
580#endif
581 default:
582 break;
583 }
584 return false;
585}
586
587/**
588 * \brief Standard endpoint request to halt an endpoint
589 *
590 * \return true if success
591 */
592#if (0!=USB_DEVICE_MAX_EP)
593static bool udc_req_std_ep_set_feature(void)
594{
595 if (udd_g_ctrlreq.req.wLength) {
596 return false;
597 }
598 if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) {
599 udd_ep_abort(udd_g_ctrlreq.req.wIndex & 0xFF);
600 return udd_ep_set_halt(udd_g_ctrlreq.req.wIndex & 0xFF);
601 }
602 return false;
603}
604#endif
605
606/**
607 * \brief Change the address of device
608 * Callback called at the end of request set address
609 */
610static void udc_valid_address(void)
611{
612 udd_set_address(udd_g_ctrlreq.req.wValue & 0x7F);
613}
614
615/**
616 * \brief Standard device request to set device address
617 *
618 * \return true if success
619 */
620static bool udc_req_std_dev_set_address(void)
621{
622 if (udd_g_ctrlreq.req.wLength) {
623 return false;
624 }
625
626 // The address must be changed at the end of setup request after the handshake
627 // then we use a callback to change address
628 udd_g_ctrlreq.callback = udc_valid_address;
629 return true;
630}
631
632/**
633 * \brief Standard device request to get device string descriptor
634 *
635 * \return true if success
636 */
637static bool udc_req_std_dev_get_str_desc(void)
638{
639 uint8_t i;
640 const uint8_t *str;
641 uint8_t str_length = 0;
642
643 // Link payload pointer to the string corresponding at request
644 switch (udd_g_ctrlreq.req.wValue & 0xff) {
645 case 0:
646 udd_set_setup_payload((uint8_t *) &udc_string_desc_languageid,
647 sizeof(udc_string_desc_languageid));
648 break;
649
650#ifdef USB_DEVICE_MANUFACTURE_NAME
651 case 1:
652 str_length = USB_DEVICE_MANUFACTURE_NAME_SIZE;
653 str = udc_string_manufacturer_name;
654 break;
655#endif
656#ifdef USB_DEVICE_PRODUCT_NAME
657 case 2:
658 str_length = USB_DEVICE_PRODUCT_NAME_SIZE;
659 str = udc_string_product_name;
660 break;
661#endif
662 case 3:
663 str = udc_get_string_serial_name();
664 str_length = usb_device_serial_name_size;
665 break;
666 default:
667#ifdef UDC_GET_EXTRA_STRING
668 if (UDC_GET_EXTRA_STRING()) {
669 break;
670 }
671#endif
672 return false;
673 }
674
675 if (str_length) {
676 for(i = 0; i < str_length; i++) {
677 udc_string_desc.string[i] = cpu_to_le16((le16_t)str[i]);
678 }
679
680 udc_string_desc.header.bLength = 2 + (str_length) * 2;
681 udd_set_setup_payload(
682 (uint8_t *) &udc_string_desc,
683 udc_string_desc.header.bLength);
684 }
685
686 return true;
687}
688
689/**
690 * \brief Standard device request to get descriptors about USB device
691 *
692 * \return true if success
693 */
694static bool udc_req_std_dev_get_descriptor(void)
695{
696 uint8_t conf_num;
697
698 conf_num = udd_g_ctrlreq.req.wValue & 0xff;
699
700 // Check descriptor ID
701 switch ((uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
702 case USB_DT_DEVICE:
703 // Device descriptor requested
704#ifdef USB_DEVICE_HS_SUPPORT
705 if (!udd_is_high_speed()) {
706 udd_set_setup_payload(
707 (uint8_t *) udc_config.confdev_hs,
708 udc_config.confdev_hs->bLength);
709 } else
710#endif
711 {
712 udd_set_setup_payload(
713 (uint8_t *) udc_config.confdev_lsfs,
714 udc_config.confdev_lsfs->bLength);
715 }
716 break;
717
718 case USB_DT_CONFIGURATION:
719 // Configuration descriptor requested
720#ifdef USB_DEVICE_HS_SUPPORT
721 if (udd_is_high_speed()) {
722 // HS descriptor
723 if (conf_num >= udc_config.confdev_hs->bNumConfigurations) {
724 return false;
725 }
726 udd_set_setup_payload(
727 (uint8_t *)udc_config.conf_hs[conf_num].desc,
728 le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength));
729 } else
730#endif
731 {
732 // FS descriptor
733 if (conf_num >= udc_config.confdev_lsfs->bNumConfigurations) {
734 return false;
735 }
736 udd_set_setup_payload(
737 (uint8_t *)udc_config.conf_lsfs[conf_num].desc,
738 le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength));
739 }
740 ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType =
741 USB_DT_CONFIGURATION;
742 break;
743
744#ifdef USB_DEVICE_HS_SUPPORT
745 case USB_DT_DEVICE_QUALIFIER:
746 // Device qualifier descriptor requested
747 udd_set_setup_payload( (uint8_t *) udc_config.qualifier,
748 udc_config.qualifier->bLength);
749 break;
750
751 case USB_DT_OTHER_SPEED_CONFIGURATION:
752 // Other configuration descriptor requested
753 if (!udd_is_high_speed()) {
754 // HS descriptor
755 if (conf_num >= udc_config.confdev_hs->bNumConfigurations) {
756 return false;
757 }
758 udd_set_setup_payload(
759 (uint8_t *)udc_config.conf_hs[conf_num].desc,
760 le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength));
761 } else {
762 // FS descriptor
763 if (conf_num >= udc_config.confdev_lsfs->bNumConfigurations) {
764 return false;
765 }
766 udd_set_setup_payload(
767 (uint8_t *)udc_config.conf_lsfs[conf_num].desc,
768 le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength));
769 }
770 ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType =
771 USB_DT_OTHER_SPEED_CONFIGURATION;
772 break;
773#endif
774
775 case USB_DT_BOS:
776 // Device BOS descriptor requested
777 if (udc_config.conf_bos == NULL) {
778 return false;
779 }
780 udd_set_setup_payload( (uint8_t *) udc_config.conf_bos,
781 udc_config.conf_bos->wTotalLength);
782 break;
783
784 case USB_DT_STRING:
785 // String descriptor requested
786 if (!udc_req_std_dev_get_str_desc()) {
787 return false;
788 }
789 break;
790
791 default:
792 // Unknown descriptor requested
793 return false;
794 }
795 // if the descriptor is larger than length requested, then reduce it
796 if (udd_g_ctrlreq.req.wLength < udd_g_ctrlreq.payload_size) {
797 udd_g_ctrlreq.payload_size = udd_g_ctrlreq.req.wLength;
798 }
799 return true;
800}
801
802/**
803 * \brief Standard device request to get configuration number
804 *
805 * \return true if success
806 */
807static bool udc_req_std_dev_get_configuration(void)
808{
809 if (udd_g_ctrlreq.req.wLength != 1) {
810 return false;
811 }
812
813 udd_set_setup_payload(&udc_num_configuration,1);
814 return true;
815}
816
817/**
818 * \brief Standard device request to enable a configuration
819 *
820 * \return true if success
821 */
822static bool udc_req_std_dev_set_configuration(void)
823{
824 uint8_t iface_num;
825
826 // Check request length
827 if (udd_g_ctrlreq.req.wLength) {
828 return false;
829 }
830 // Authorize configuration only if the address is valid
831 if (!udd_getaddress()) {
832 return false;
833 }
834 // Check the configuration number requested
835#ifdef USB_DEVICE_HS_SUPPORT
836 if (udd_is_high_speed()) {
837 // HS descriptor
838 if ((udd_g_ctrlreq.req.wValue & 0xFF) >
839 udc_config.confdev_hs->bNumConfigurations) {
840 return false;
841 }
842 } else
843#endif
844 {
845 // FS descriptor
846 if ((udd_g_ctrlreq.req.wValue & 0xFF) >
847 udc_config.confdev_lsfs->bNumConfigurations) {
848 return false;
849 }
850 }
851
852 // Reset current configuration
853 udc_reset();
854
855 // Enable new configuration
856 udc_num_configuration = udd_g_ctrlreq.req.wValue & 0xFF;
857 if (udc_num_configuration == 0) {
858 return true; // Default empty configuration requested
859 }
860 // Update pointer of the configuration descriptor
861#ifdef USB_DEVICE_HS_SUPPORT
862 if (udd_is_high_speed()) {
863 // HS descriptor
864 udc_ptr_conf = &udc_config.conf_hs[udc_num_configuration - 1];
865 } else
866#endif
867 {
868 // FS descriptor
869 udc_ptr_conf = &udc_config.conf_lsfs[udc_num_configuration - 1];
870 }
871 // Enable all interfaces of the selected configuration
872 for (iface_num = 0; iface_num < udc_ptr_conf->desc->bNumInterfaces;
873 iface_num++) {
874 if (!udc_iface_enable(iface_num, 0)) {
875 return false;
876 }
877 }
878 return true;
879}
880
881/**
882 * \brief Standard interface request
883 * to get the alternate setting number of an interface
884 *
885 * \return true if success
886 */
887static bool udc_req_std_iface_get_setting(void)
888{
889 uint8_t iface_num;
890 udi_api_t UDC_DESC_STORAGE *udi_api;
891
892 if (udd_g_ctrlreq.req.wLength != 1) {
893 return false; // Error in request
894 }
895 if (!udc_num_configuration) {
896 return false; // The device is not is configured state yet
897 }
898
899 // Check the interface number included in the request
900 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
901 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
902 return false;
903 }
904
905 // Select first alternate setting of the interface to update udc_ptr_iface
906 // before call iface->getsetting()
907 if (!udc_update_iface_desc(iface_num, 0)) {
908 return false;
909 }
910 // Get alternate setting from UDI
911 udi_api = udc_ptr_conf->udi_apis[iface_num];
912 udc_iface_setting = udi_api->getsetting();
913
914 // Link value to payload pointer of request
915 udd_set_setup_payload(&udc_iface_setting,1);
916 return true;
917}
918
919/**
920 * \brief Standard interface request
921 * to set an alternate setting of an interface
922 *
923 * \return true if success
924 */
925static bool udc_req_std_iface_set_setting(void)
926{
927 uint8_t iface_num, setting_num;
928
929 if (udd_g_ctrlreq.req.wLength) {
930 return false; // Error in request
931 }
932 if (!udc_num_configuration) {
933 return false; // The device is not is configured state yet
934 }
935
936 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
937 setting_num = udd_g_ctrlreq.req.wValue & 0xFF;
938
939 // Disable current setting
940 if (!udc_iface_disable(iface_num)) {
941 return false;
942 }
943
944 // Enable new setting
945 return udc_iface_enable(iface_num, setting_num);
946}
947
948/**
949 * \brief Main routine to manage the standard USB SETUP request
950 *
951 * \return true if the request is supported
952 */
953static bool udc_reqstd(void)
954{
955 if (Udd_setup_is_in()) {
956 // GET Standard Requests
957 if (udd_g_ctrlreq.req.wLength == 0) {
958 return false; // Error for USB host
959 }
960
961 if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) {
962 // Standard Get Device request
963 switch (udd_g_ctrlreq.req.bRequest) {
964 case USB_REQ_GET_STATUS:
965 return udc_req_std_dev_get_status();
966 case USB_REQ_GET_DESCRIPTOR:
967 return udc_req_std_dev_get_descriptor();
968 case USB_REQ_GET_CONFIGURATION:
969 return udc_req_std_dev_get_configuration();
970 default:
971 break;
972 }
973 }
974
975 if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) {
976 // Standard Get Interface request
977 switch (udd_g_ctrlreq.req.bRequest) {
978 case USB_REQ_GET_INTERFACE:
979 return udc_req_std_iface_get_setting();
980 default:
981 break;
982 }
983 }
984#if (0!=USB_DEVICE_MAX_EP)
985 if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) {
986 // Standard Get Endpoint request
987 switch (udd_g_ctrlreq.req.bRequest) {
988 case USB_REQ_GET_STATUS:
989 return udc_req_std_ep_get_status();
990 default:
991 break;
992 }
993 }
994#endif
995 } else {
996 // SET Standard Requests
997 if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) {
998 // Standard Set Device request
999 switch (udd_g_ctrlreq.req.bRequest) {
1000 case USB_REQ_SET_ADDRESS:
1001 return udc_req_std_dev_set_address();
1002 case USB_REQ_CLEAR_FEATURE:
1003 return udc_req_std_dev_clear_feature();
1004 case USB_REQ_SET_FEATURE:
1005 return udc_req_std_dev_set_feature();
1006 case USB_REQ_SET_CONFIGURATION:
1007 return udc_req_std_dev_set_configuration();
1008 case USB_REQ_SET_DESCRIPTOR:
1009 /* Not supported (defined as optional by the USB 2.0 spec) */
1010 break;
1011 default:
1012 break;
1013 }
1014 }
1015
1016 if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) {
1017 // Standard Set Interface request
1018 switch (udd_g_ctrlreq.req.bRequest) {
1019 case USB_REQ_SET_INTERFACE:
1020 return udc_req_std_iface_set_setting();
1021 default:
1022 break;
1023 }
1024 }
1025#if (0!=USB_DEVICE_MAX_EP)
1026 if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) {
1027 // Standard Set Endpoint request
1028 switch (udd_g_ctrlreq.req.bRequest) {
1029 case USB_REQ_CLEAR_FEATURE:
1030 return udc_req_std_ep_clear_feature();
1031 case USB_REQ_SET_FEATURE:
1032 return udc_req_std_ep_set_feature();
1033 default:
1034 break;
1035 }
1036 }
1037#endif
1038 }
1039 return false;
1040}
1041
1042/**
1043 * \brief Send the SETUP interface request to UDI
1044 *
1045 * \return true if the request is supported
1046 */
1047static bool udc_req_iface(void)
1048{
1049 uint8_t iface_num;
1050 udi_api_t UDC_DESC_STORAGE *udi_api;
1051
1052 if (0 == udc_num_configuration) {
1053 return false; // The device is not is configured state yet
1054 }
1055 // Check interface number
1056 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
1057 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
1058 return false;
1059 }
1060
1061 //* To update udc_ptr_iface with the selected interface in request
1062 // Select first alternate setting of interface to update udc_ptr_iface
1063 // before calling udi_api->getsetting()
1064 if (!udc_update_iface_desc(iface_num, 0)) {
1065 return false;
1066 }
1067 // Select the interface with the current alternate setting
1068 udi_api = udc_ptr_conf->udi_apis[iface_num];
1069 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
1070 return false;
1071 }
1072
1073 // Send the SETUP request to the UDI corresponding to the interface number
1074 return udi_api->setup();
1075}
1076
1077/**
1078 * \brief Send the SETUP interface request to UDI
1079 *
1080 * \return true if the request is supported
1081 */
1082static bool udc_req_ep(void)
1083{
1084 uint8_t iface_num;
1085 udi_api_t UDC_DESC_STORAGE *udi_api;
1086
1087 if (0 == udc_num_configuration) {
1088 return false; // The device is not is configured state yet
1089 }
1090 // Send this request on all enabled interfaces
1091 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
1092 for (iface_num = 0; iface_num < udc_ptr_conf->desc->bNumInterfaces;
1093 iface_num++) {
1094 // Select the interface with the current alternate setting
1095 udi_api = udc_ptr_conf->udi_apis[iface_num];
1096 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
1097 return false;
1098 }
1099
1100 // Send the SETUP request to the UDI
1101 if (udi_api->setup()) {
1102 return true;
1103 }
1104 }
1105 return false;
1106}
1107
1108/**
1109 * \brief Main routine to manage the USB SETUP request.
1110 *
1111 * This function parses a USB SETUP request and submits an appropriate
1112 * response back to the host or, in the case of SETUP OUT requests
1113 * with data, sets up a buffer for receiving the data payload.
1114 *
1115 * The main standard requests defined by the USB 2.0 standard are handled
1116 * internally. The interface requests are sent to UDI, and the specific request
1117 * sent to a specific application callback.
1118 *
1119 * \return true if the request is supported, else the request is stalled by UDD
1120 */
1121bool udc_process_setup(void)
1122{
1123 // By default no data (receive/send) and no callbacks registered
1124 udd_g_ctrlreq.payload_size = 0;
1125 udd_g_ctrlreq.callback = NULL;
1126 udd_g_ctrlreq.over_under_run = NULL;
1127
1128 if (Udd_setup_is_in()) {
1129 if (udd_g_ctrlreq.req.wLength == 0) {
1130 return false; // Error from USB host
1131 }
1132 }
1133
1134 // If standard request then try to decode it in UDC
1135 if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) {
1136 if (udc_reqstd()) {
1137 return true;
1138 }
1139 }
1140
1141 // If interface request then try to decode it in UDI
1142 if (Udd_setup_recipient() == USB_REQ_RECIP_INTERFACE) {
1143 if (udc_req_iface()) {
1144 return true;
1145 }
1146 }
1147
1148 // If endpoint request then try to decode it in UDI
1149 if (Udd_setup_recipient() == USB_REQ_RECIP_ENDPOINT) {
1150 if (udc_req_ep()) {
1151 return true;
1152 }
1153 }
1154
1155 // Here SETUP request unknown by UDC and UDIs
1156#ifdef USB_DEVICE_SPECIFIC_REQUEST
1157 // Try to decode it in specific callback
1158 return USB_DEVICE_SPECIFIC_REQUEST(); // Ex: Vendor request,...
1159#else
1160 return false;
1161#endif
1162}
1163
1164//! @}
diff --git a/tmk_core/protocol/arm_atsam/usb/udc.h b/tmk_core/protocol/arm_atsam/usb/udc.h
new file mode 100644
index 000000000..c88a442cb
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udc.h
@@ -0,0 +1,260 @@
1/**
2 * \file
3 *
4 * \brief Interface of the USB Device Controller (UDC)
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDC_H_
48#define _UDC_H_
49
50#include "conf_usb.h"
51#include "usb_protocol.h"
52#include "udc_desc.h"
53#include "udd.h"
54
55#if USB_DEVICE_VENDOR_ID == 0
56# error USB_DEVICE_VENDOR_ID cannot be equal to 0
57#endif
58
59#if USB_DEVICE_PRODUCT_ID == 0
60# error USB_DEVICE_PRODUCT_ID cannot be equal to 0
61#endif
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67/**
68 * \ingroup usb_device_group
69 * \defgroup udc_group USB Device Controller (UDC)
70 *
71 * The UDC provides a high-level abstraction of the usb device.
72 * You can use these functions to control the main device state
73 * (start/attach/wakeup).
74 *
75 * \section USB_DEVICE_CONF USB Device Custom configuration
76 * The following USB Device configuration must be included in the conf_usb.h
77 * file of the application.
78 *
79 * USB_DEVICE_VENDOR_ID (Word)<br>
80 * Vendor ID provided by USB org (ATMEL 0x03EB).
81 *
82 * USB_DEVICE_PRODUCT_ID (Word)<br>
83 * Product ID (Referenced in usb_atmel.h).
84 *
85 * USB_DEVICE_MAJOR_VERSION (Byte)<br>
86 * Major version of the device
87 *
88 * USB_DEVICE_MINOR_VERSION (Byte)<br>
89 * Minor version of the device
90 *
91 * USB_DEVICE_MANUFACTURE_NAME (string)<br>
92 * ASCII name for the manufacture
93 *
94 * USB_DEVICE_PRODUCT_NAME (string)<br>
95 * ASCII name for the product
96 *
97 * USB_DEVICE_SERIAL_NAME (string)<br>
98 * ASCII name to enable and set a serial number
99 *
100 * USB_DEVICE_POWER (Numeric)<br>
101 * (unit mA) Maximum device power
102 *
103 * USB_DEVICE_ATTR (Byte)<br>
104 * USB attributes available:
105 * - USB_CONFIG_ATTR_SELF_POWERED
106 * - USB_CONFIG_ATTR_REMOTE_WAKEUP
107 * Note: if remote wake enabled then defines remotewakeup callbacks,
108 * see Table 5-2. External API from UDC - Callback
109 *
110 * USB_DEVICE_LOW_SPEED (Only defined)<br>
111 * Force the USB Device to run in low speed
112 *
113 * USB_DEVICE_HS_SUPPORT (Only defined)<br>
114 * Authorize the USB Device to run in high speed
115 *
116 * USB_DEVICE_MAX_EP (Byte)<br>
117 * Define the maximum endpoint number used by the USB Device.<br>
118 * This one is already defined in UDI default configuration.
119 * Ex:
120 * - When endpoint control 0x00, endpoint 0x01 and
121 * endpoint 0x82 is used then USB_DEVICE_MAX_EP=2
122 * - When only endpoint control 0x00 is used then USB_DEVICE_MAX_EP=0
123 * - When endpoint 0x01 and endpoint 0x81 is used then USB_DEVICE_MAX_EP=1<br>
124 * (configuration not possible on USBB interface)
125 * @{
126 */
127
128/**
129 * \brief Authorizes the VBUS event
130 *
131 * \return true, if the VBUS monitoring is possible.
132 *
133 * \section udc_vbus_monitoring VBus monitoring used cases
134 *
135 * The VBus monitoring is used only for USB SELF Power application.
136 *
137 * - By default the USB device is automatically attached when Vbus is high
138 * or when USB is start for devices without internal Vbus monitoring.
139 * conf_usb.h file does not contains define USB_DEVICE_ATTACH_AUTO_DISABLE.
140 * \code //#define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
141 *
142 * - Add custom VBUS monitoring. conf_usb.h file contains define
143 * USB_DEVICE_ATTACH_AUTO_DISABLE:
144 * \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
145 * User C file contains:
146 * \code
147 // Authorize VBUS monitoring
148 if (!udc_include_vbus_monitoring()) {
149 // Implement custom VBUS monitoring via GPIO or other
150 }
151 Event_VBUS_present() // VBUS interrupt or GPIO interrupt or other
152 {
153 // Attach USB Device
154 udc_attach();
155 }
156\endcode
157 *
158 * - Case of battery charging. conf_usb.h file contains define
159 * USB_DEVICE_ATTACH_AUTO_DISABLE:
160 * \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
161 * User C file contains:
162 * \code
163 Event VBUS present() // VBUS interrupt or GPIO interrupt or ..
164 {
165 // Authorize battery charging, but wait key press to start USB.
166 }
167 Event Key press()
168 {
169 // Stop batteries charging
170 // Start USB
171 udc_attach();
172 }
173\endcode
174 */
175static inline bool udc_include_vbus_monitoring(void)
176{
177 return udd_include_vbus_monitoring();
178}
179
180/*! \brief Start the USB Device stack
181 */
182void udc_start(void);
183
184/*! \brief Stop the USB Device stack
185 */
186void udc_stop(void);
187
188/**
189 * \brief Attach device to the bus when possible
190 *
191 * \warning If a VBus control is included in driver,
192 * then it will attach device when an acceptable Vbus
193 * level from the host is detected.
194 */
195static inline void udc_attach(void)
196{
197 udd_attach();
198}
199
200/**
201 * \brief Detaches the device from the bus
202 *
203 * The driver must remove pull-up on USB line D- or D+.
204 */
205static inline void udc_detach(void)
206{
207 udd_detach();
208}
209
210/*! \brief The USB driver sends a resume signal called \e "Upstream Resume"
211 * This is authorized only when the remote wakeup feature is enabled by host.
212 */
213static inline void udc_remotewakeup(void)
214{
215 udd_send_remotewakeup();
216}
217
218/**
219 * \brief Returns a pointer on the current interface descriptor
220 *
221 * \return pointer on the current interface descriptor.
222 */
223usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void);
224
225//@}
226
227/**
228 * \ingroup usb_group
229 * \defgroup usb_device_group USB Stack Device
230 *
231 * This module includes USB Stack Device implementation.
232 * The stack is divided in three parts:
233 * - USB Device Controller (UDC) provides USB chapter 9 compliance
234 * - USB Device Interface (UDI) provides USB Class compliance
235 * - USB Device Driver (UDD) provides USB Driver for each Atmel MCU
236
237 * Many USB Device applications can be implemented on Atmel MCU.
238 * Atmel provides many application notes for different applications:
239 * - AVR4900, provides general information about Device Stack
240 * - AVR4901, explains how to create a new class
241 * - AVR4902, explains how to create a composite device
242 * - AVR49xx, all device classes provided in ASF have an application note
243 *
244 * A basic USB knowledge is required to understand the USB Device
245 * Class application notes (HID,MS,CDC,PHDC,...).
246 * Then, to create an USB device with
247 * only one class provided by ASF, refer directly to the application note
248 * corresponding to this USB class. The USB Device application note for
249 * New Class and Composite is dedicated to advanced USB users.
250 *
251 * @{
252 */
253
254//! @}
255
256#ifdef __cplusplus
257}
258#endif
259
260#endif // _UDC_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udc_desc.h b/tmk_core/protocol/arm_atsam/usb/udc_desc.h
new file mode 100644
index 000000000..9cab03dcb
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udc_desc.h
@@ -0,0 +1,135 @@
1/**
2 * \file
3 *
4 * \brief Common API for USB Device Interface
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDC_DESC_H_
48#define _UDC_DESC_H_
49
50#include "conf_usb.h"
51#include "usb_protocol.h"
52#include "udi.h"
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58/**
59 * \ingroup udc_group
60 * \defgroup udc_desc_group USB Device Descriptor
61 *
62 * @{
63 */
64
65/**
66 * \brief Defines the memory's location of USB descriptors
67 *
68 * By default the Descriptor is stored in RAM
69 * (UDC_DESC_STORAGE is defined empty).
70 *
71 * If you have need to free RAM space,
72 * it is possible to put descriptor in flash in following case:
73 * - USB driver authorize flash transfer (USBB on UC3 and USB on Mega)
74 * - USB Device is not high speed (UDC no need to change USB descriptors)
75 *
76 * For UC3 application used "const".
77 *
78 * For Mega application used "code".
79 */
80#define UDC_DESC_STORAGE
81 // Descriptor storage in internal RAM
82#if (defined UDC_DATA_USE_HRAM_SUPPORT)
83#if defined(__GNUC__)
84#define UDC_DATA(x) COMPILER_WORD_ALIGNED __attribute__((__section__(".data_hram0")))
85#define UDC_BSS(x) COMPILER_ALIGNED(x) __attribute__((__section__(".bss_hram0")))
86#elif defined(__ICCAVR32__)
87#define UDC_DATA(x) COMPILER_ALIGNED(x) __data32
88#define UDC_BSS(x) COMPILER_ALIGNED(x) __data32
89#endif
90#else
91#define UDC_DATA(x) COMPILER_ALIGNED(x)
92#define UDC_BSS(x) COMPILER_ALIGNED(x)
93#endif
94
95
96
97/**
98 * \brief Configuration descriptor and UDI link for one USB speed
99 */
100typedef struct {
101 //! USB configuration descriptor
102 usb_conf_desc_t UDC_DESC_STORAGE *desc;
103 //! Array of UDI API pointer
104 udi_api_t UDC_DESC_STORAGE *UDC_DESC_STORAGE * udi_apis;
105} udc_config_speed_t;
106
107
108/**
109 * \brief All information about the USB Device
110 */
111typedef struct {
112 //! USB device descriptor for low or full speed
113 usb_dev_desc_t UDC_DESC_STORAGE *confdev_lsfs;
114 //! USB configuration descriptor and UDI API pointers for low or full speed
115 udc_config_speed_t UDC_DESC_STORAGE *conf_lsfs;
116#ifdef USB_DEVICE_HS_SUPPORT
117 //! USB device descriptor for high speed
118 usb_dev_desc_t UDC_DESC_STORAGE *confdev_hs;
119 //! USB device qualifier, only use in high speed mode
120 usb_dev_qual_desc_t UDC_DESC_STORAGE *qualifier;
121 //! USB configuration descriptor and UDI API pointers for high speed
122 udc_config_speed_t UDC_DESC_STORAGE *conf_hs;
123#endif
124 usb_dev_bos_desc_t UDC_DESC_STORAGE *conf_bos;
125} udc_config_t;
126
127//! Global variables of USB Device Descriptor and UDI links
128extern UDC_DESC_STORAGE udc_config_t udc_config;
129
130//@}
131
132#ifdef __cplusplus
133}
134#endif
135#endif // _UDC_DESC_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udd.h b/tmk_core/protocol/arm_atsam/usb/udd.h
new file mode 100644
index 000000000..b580e5847
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udd.h
@@ -0,0 +1,396 @@
1/**
2 * \file
3 *
4 * \brief Common API for USB Device Drivers (UDD)
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDD_H_
48#define _UDD_H_
49
50#include "usb_protocol.h"
51#include "udc_desc.h"
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57/**
58 * \ingroup usb_device_group
59 * \defgroup udd_group USB Device Driver (UDD)
60 *
61 * The UDD driver provides a low-level abstraction of the device
62 * controller hardware. Most events coming from the hardware such as
63 * interrupts, which may cause the UDD to call into the UDC and UDI.
64 *
65 * @{
66 */
67
68//! \brief Endpoint identifier
69typedef uint8_t udd_ep_id_t;
70
71//! \brief Endpoint transfer status
72//! Returned in parameters of callback register via udd_ep_run routine.
73typedef enum {
74 UDD_EP_TRANSFER_OK = 0,
75 UDD_EP_TRANSFER_ABORT = 1,
76} udd_ep_status_t;
77
78/**
79 * \brief Global variable to give and record information of the setup request management
80 *
81 * This global variable allows to decode and response a setup request.
82 * It can be updated by udc_process_setup() from UDC or *setup() from UDIs.
83 */
84typedef struct {
85 //! Data received in USB SETUP packet
86 //! Note: The swap of "req.wValues" from uin16_t to le16_t is done by UDD.
87 usb_setup_req_t req;
88
89 //! Point to buffer to send or fill with data following SETUP packet
90 //! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
91 uint8_t *payload;
92
93 //! Size of buffer to send or fill, and content the number of byte transfered
94 uint16_t payload_size;
95
96 //! Callback called after reception of ZLP from setup request
97 void (*callback) (void);
98
99 //! Callback called when the buffer given (.payload) is full or empty.
100 //! This one return false to abort data transfer, or true with a new buffer in .payload.
101 bool(*over_under_run) (void);
102} udd_ctrl_request_t;
103extern udd_ctrl_request_t udd_g_ctrlreq;
104
105//! Return true if the setup request \a udd_g_ctrlreq indicates IN data transfer
106#define Udd_setup_is_in() \
107 (USB_REQ_DIR_IN == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
108
109//! Return true if the setup request \a udd_g_ctrlreq indicates OUT data transfer
110#define Udd_setup_is_out() \
111 (USB_REQ_DIR_OUT == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
112
113//! Return the type of the SETUP request \a udd_g_ctrlreq. \see usb_reqtype.
114#define Udd_setup_type() \
115 (udd_g_ctrlreq.req.bmRequestType & USB_REQ_TYPE_MASK)
116
117//! Return the recipient of the SETUP request \a udd_g_ctrlreq. \see usb_recipient
118#define Udd_setup_recipient() \
119 (udd_g_ctrlreq.req.bmRequestType & USB_REQ_RECIP_MASK)
120
121/**
122 * \brief End of halt callback function type.
123 * Registered by routine udd_ep_wait_stall_clear()
124 * Callback called when endpoint stall is cleared.
125 */
126typedef void (*udd_callback_halt_cleared_t) (void);
127
128/**
129 * \brief End of transfer callback function type.
130 * Registered by routine udd_ep_run()
131 * Callback called by USB interrupt after data transfer or abort (reset,...).
132 *
133 * \param status UDD_EP_TRANSFER_OK, if transfer is complete
134 * \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
135 * \param n number of data transfered
136 */
137typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
138 iram_size_t nb_transfered, udd_ep_id_t ep);
139
140/**
141 * \brief Authorizes the VBUS event
142 *
143 * \return true, if the VBUS monitoring is possible.
144 */
145bool udd_include_vbus_monitoring(void);
146
147/**
148 * \brief Enables the USB Device mode
149 */
150void udd_enable(void);
151
152/**
153 * \brief Disables the USB Device mode
154 */
155void udd_disable(void);
156
157/**
158 * \brief Attach device to the bus when possible
159 *
160 * \warning If a VBus control is included in driver,
161 * then it will attach device when an acceptable Vbus
162 * level from the host is detected.
163 */
164void udd_attach(void);
165
166/**
167 * \brief Detaches the device from the bus
168 *
169 * The driver must remove pull-up on USB line D- or D+.
170 */
171void udd_detach(void);
172
173/**
174 * \brief Test whether the USB Device Controller is running at high
175 * speed or not.
176 *
177 * \return \c true if the Device is running at high speed mode, otherwise \c false.
178 */
179bool udd_is_high_speed(void);
180
181/**
182 * \brief Changes the USB address of device
183 *
184 * \param address New USB address
185 */
186void udd_set_address(uint8_t address);
187
188/**
189 * \brief Returns the USB address of device
190 *
191 * \return USB address
192 */
193uint8_t udd_getaddress(void);
194
195/**
196 * \brief Returns the current start of frame number
197 *
198 * \return current start of frame number.
199 */
200uint16_t udd_get_frame_number(void);
201
202/**
203 * \brief Returns the current micro start of frame number
204 *
205 * \return current micro start of frame number required in high speed mode.
206 */
207uint16_t udd_get_micro_frame_number(void);
208
209/*! \brief The USB driver sends a resume signal called Upstream Resume
210 */
211void udd_send_remotewakeup(void);
212
213/**
214 * \brief Load setup payload
215 *
216 * \param payload Pointer on payload
217 * \param payload_size Size of payload
218 */
219void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size );
220
221
222/**
223 * \name Endpoint Management
224 *
225 * The following functions allow drivers to create and remove
226 * endpoints, as well as set, clear and query their "halted" and
227 * "wedged" states.
228 */
229//@{
230
231#if (USB_DEVICE_MAX_EP != 0)
232
233/**
234 * \brief Configures and enables an endpoint
235 *
236 * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
237 * \param bmAttributes Attributes of endpoint declared in the descriptor.
238 * \param MaxEndpointSize Endpoint maximum size
239 *
240 * \return \c 1 if the endpoint is enabled, otherwise \c 0.
241 */
242bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
243 uint16_t MaxEndpointSize);
244
245/**
246 * \brief Disables an endpoint
247 *
248 * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
249 */
250void udd_ep_free(udd_ep_id_t ep);
251
252/**
253 * \brief Check if the endpoint \a ep is halted.
254 *
255 * \param ep The ID of the endpoint to check.
256 *
257 * \return \c 1 if \a ep is halted, otherwise \c 0.
258 */
259bool udd_ep_is_halted(udd_ep_id_t ep);
260
261/**
262 * \brief Set the halted state of the endpoint \a ep
263 *
264 * After calling this function, any transaction on \a ep will result
265 * in a STALL handshake being sent. Any pending transactions will be
266 * performed first, however.
267 *
268 * \param ep The ID of the endpoint to be halted
269 *
270 * \return \c 1 if \a ep is halted, otherwise \c 0.
271 */
272bool udd_ep_set_halt(udd_ep_id_t ep);
273
274/**
275 * \brief Clear the halted state of the endpoint \a ep
276 *
277 * After calling this function, any transaction on \a ep will
278 * be handled normally, i.e. a STALL handshake will not be sent, and
279 * the data toggle sequence will start at DATA0.
280 *
281 * \param ep The ID of the endpoint to be un-halted
282 *
283 * \return \c 1 if function was successfully done, otherwise \c 0.
284 */
285bool udd_ep_clear_halt(udd_ep_id_t ep);
286
287/**
288 * \brief Registers a callback to call when endpoint halt is cleared
289 *
290 * \param ep The ID of the endpoint to use
291 * \param callback NULL or function to call when endpoint halt is cleared
292 *
293 * \warning if the endpoint is not halted then the \a callback is called immediately.
294 *
295 * \return \c 1 if the register is accepted, otherwise \c 0.
296 */
297bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
298 udd_callback_halt_cleared_t callback);
299
300/**
301 * \brief Allows to receive or send data on an endpoint
302 *
303 * The driver uses a specific DMA USB to transfer data
304 * from internal RAM to endpoint, if this one is available.
305 * When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
306 * The \a callback returns the transfer status and eventually the number of byte transfered.
307 * Note: The control endpoint is not authorized.
308 *
309 * \param ep The ID of the endpoint to use
310 * \param b_shortpacket Enabled automatic short packet
311 * \param buf Buffer on Internal RAM to send or fill.
312 * It must be align, then use COMPILER_WORD_ALIGNED.
313 * \param buf_size Buffer size to send or fill
314 * \param callback NULL or function to call at the end of transfer
315 *
316 * \warning About \a b_shortpacket, for IN endpoint it means that a short packet
317 * (or a Zero Length Packet) will be sent to the USB line to properly close the usb
318 * transfer at the end of the data transfer.
319 * For Bulk and Interrupt OUT endpoint, it will automatically stop the transfer
320 * at the end of the data transfer (received short packet).
321 *
322 * \return \c 1 if function was successfully done, otherwise \c 0.
323 */
324bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket,
325 uint8_t *buf, iram_size_t buf_size,
326 udd_callback_trans_t callback);
327/**
328 * \brief Aborts transfer on going on endpoint
329 *
330 * If a transfer is on going, then it is stopped and
331 * the callback registered is called to signal the end of transfer.
332 * Note: The control endpoint is not authorized.
333 *
334 * \param ep Endpoint to abort
335 */
336void udd_ep_abort(udd_ep_id_t ep);
337
338#endif
339
340//@}
341
342
343/**
344 * \name High speed test mode management
345 *
346 * The following functions allow the device to jump to a specific test mode required in high speed mode.
347 */
348//@{
349void udd_test_mode_j(void);
350void udd_test_mode_k(void);
351void udd_test_mode_se0_nak(void);
352void udd_test_mode_packet(void);
353//@}
354
355
356/**
357 * \name UDC callbacks to provide for UDD
358 *
359 * The following callbacks are used by UDD.
360 */
361//@{
362
363/**
364 * \brief Decodes and manages a setup request
365 *
366 * The driver call it when a SETUP packet is received.
367 * The \c udd_g_ctrlreq contains the data of SETUP packet.
368 * If this callback accepts the setup request then it must
369 * return \c 1 and eventually update \c udd_g_ctrlreq to send or receive data.
370 *
371 * \return \c 1 if the request is accepted, otherwise \c 0.
372 */
373extern bool udc_process_setup(void);
374
375/**
376 * \brief Reset the UDC
377 *
378 * The UDC must reset all configuration.
379 */
380extern void udc_reset(void);
381
382/**
383 * \brief To signal that a SOF is occurred
384 *
385 * The UDC must send the signal to all UDIs enabled
386 */
387extern void udc_sof_notify(void);
388
389//@}
390
391//@}
392
393#ifdef __cplusplus
394}
395#endif
396#endif // _UDD_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi.h b/tmk_core/protocol/arm_atsam/usb/udi.h
new file mode 100644
index 000000000..9e4d4baf7
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi.h
@@ -0,0 +1,133 @@
1/**
2 * \file
3 *
4 * \brief Common API for USB Device Interface
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDI_H_
48#define _UDI_H_
49
50#include "conf_usb.h"
51#include "usb_protocol.h"
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57/**
58 * \ingroup usb_device_group
59 * \defgroup udi_group USB Device Interface (UDI)
60 * The UDI provides a common API for all classes,
61 * and this is used by UDC for the main control of USB Device interface.
62 * @{
63 */
64
65/**
66 * \brief UDI API.
67 *
68 * The callbacks within this structure are called only by
69 * USB Device Controller (UDC)
70 *
71 * The udc_get_interface_desc() can be use by UDI to know the interface descriptor
72 * selected by UDC.
73 */
74typedef struct {
75 /**
76 * \brief Enable the interface.
77 *
78 * This function is called when the host selects a configuration
79 * to which this interface belongs through a Set Configuration
80 * request, and when the host selects an alternate setting of
81 * this interface through a Set Interface request.
82 *
83 * \return \c 1 if function was successfully done, otherwise \c 0.
84 */
85 bool(*enable) (void);
86
87 /**
88 * \brief Disable the interface.
89 *
90 * This function is called when this interface is currently
91 * active, and
92 * - the host selects any configuration through a Set
93 * Configuration request, or
94 * - the host issues a USB reset, or
95 * - the device is detached from the host (i.e. Vbus is no
96 * longer present)
97 */
98 void (*disable) (void);
99
100 /**
101 * \brief Handle a control request directed at an interface.
102 *
103 * This function is called when this interface is currently
104 * active and the host sends a SETUP request
105 * with this interface as the recipient.
106 *
107 * Use udd_g_ctrlreq to decode and response to SETUP request.
108 *
109 * \return \c 1 if this interface supports the SETUP request, otherwise \c 0.
110 */
111 bool(*setup) (void);
112
113 /**
114 * \brief Returns the current setting of the selected interface.
115 *
116 * This function is called when UDC when know alternate setting of selected interface.
117 *
118 * \return alternate setting of selected interface
119 */
120 uint8_t(*getsetting) (void);
121
122 /**
123 * \brief To signal that a SOF is occurred
124 */
125 void(*sof_notify) (void);
126} udi_api_t;
127
128//@}
129
130#ifdef __cplusplus
131}
132#endif
133#endif // _UDI_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc.c b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c
new file mode 100644
index 000000000..b4159d325
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c
@@ -0,0 +1,1384 @@
1/**
2 * \file
3 *
4 * \brief USB Device Communication Device Class (CDC) interface.
5 *
6 * Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#include "samd51j18a.h"
48#include "conf_usb.h"
49#include "usb_protocol.h"
50#include "usb_protocol_cdc.h"
51#include "udd.h"
52#include "udc.h"
53#include "udi_cdc.h"
54#include <string.h>
55#include "udi_cdc_conf.h"
56#include "udi_device_conf.h"
57#include "spfssf.h"
58#include "stdarg.h"
59#include "tmk_core/protocol/arm_atsam/clks.h"
60
61#ifdef CDC
62
63#ifdef UDI_CDC_LOW_RATE
64# ifdef USB_DEVICE_HS_SUPPORT
65# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE)
66# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE)
67# else
68# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_FS_SIZE)
69# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_FS_SIZE)
70# endif
71#else
72# ifdef USB_DEVICE_HS_SUPPORT
73# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE)
74# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE)
75# else
76# define UDI_CDC_TX_BUFFERS (5*UDI_CDC_DATA_EPS_FS_SIZE)
77# define UDI_CDC_RX_BUFFERS (5*UDI_CDC_DATA_EPS_FS_SIZE)
78# endif
79#endif
80
81#ifndef UDI_CDC_TX_EMPTY_NOTIFY
82# define UDI_CDC_TX_EMPTY_NOTIFY(port)
83#endif
84
85/**
86 * \ingroup udi_cdc_group
87 * \defgroup udi_cdc_group_udc Interface with USB Device Core (UDC)
88 *
89 * Structures and functions required by UDC.
90 *
91 * @{
92 */
93bool udi_cdc_comm_enable(void);
94void udi_cdc_comm_disable(void);
95bool udi_cdc_comm_setup(void);
96bool udi_cdc_data_enable(void);
97void udi_cdc_data_disable(void);
98bool udi_cdc_data_setup(void);
99uint8_t udi_cdc_getsetting(void);
100void udi_cdc_data_sof_notify(void);
101UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm = {
102 .enable = udi_cdc_comm_enable,
103 .disable = udi_cdc_comm_disable,
104 .setup = udi_cdc_comm_setup,
105 .getsetting = udi_cdc_getsetting,
106 .sof_notify = NULL
107};
108UDC_DESC_STORAGE udi_api_t udi_api_cdc_data = {
109 .enable = udi_cdc_data_enable,
110 .disable = udi_cdc_data_disable,
111 .setup = udi_cdc_data_setup,
112 .getsetting = udi_cdc_getsetting,
113 .sof_notify = udi_cdc_data_sof_notify,
114};
115//@}
116
117/**
118 * \ingroup udi_cdc_group
119 * \defgroup udi_cdc_group_internal Implementation of UDI CDC
120 *
121 * Class internal implementation
122 * @{
123 */
124
125/**
126 * \name Internal routines
127 */
128//@{
129
130/**
131 * \name Routines to control serial line
132 */
133//@{
134
135/**
136 * \brief Returns the port number corresponding at current setup request
137 *
138 * \return port number
139 */
140static uint8_t udi_cdc_setup_to_port(void);
141
142/**
143 * \brief Sends line coding to application
144 *
145 * Called after SETUP request when line coding data is received.
146 */
147static void udi_cdc_line_coding_received(void);
148
149/**
150 * \brief Records new state
151 *
152 * \param port Communication port number to manage
153 * \param b_set State is enabled if true, else disabled
154 * \param bit_mask Field to process (see CDC_SERIAL_STATE_ defines)
155 */
156static void udi_cdc_ctrl_state_change(uint8_t port, bool b_set, le16_t bit_mask);
157
158/**
159 * \brief Check and eventually notify the USB host of new state
160 *
161 * \param port Communication port number to manage
162 * \param ep Port communication endpoint
163 */
164static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep);
165
166/**
167 * \brief Ack sent of serial state message
168 * Callback called after serial state message sent
169 *
170 * \param status UDD_EP_TRANSFER_OK, if transfer finished
171 * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
172 * \param n number of data transfered
173 */
174static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
175
176//@}
177
178/**
179 * \name Routines to process data transfer
180 */
181//@{
182
183/**
184 * \brief Enable the reception of data from the USB host
185 *
186 * The value udi_cdc_rx_trans_sel indicate the RX buffer to fill.
187 *
188 * \param port Communication port number to manage
189 *
190 * \return \c 1 if function was successfully done, otherwise \c 0.
191 */
192static bool udi_cdc_rx_start(uint8_t port);
193
194/**
195 * \brief Update rx buffer management with a new data
196 * Callback called after data reception on USB line
197 *
198 * \param status UDD_EP_TRANSFER_OK, if transfer finish
199 * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
200 * \param n number of data received
201 */
202static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
203
204/**
205 * \brief Ack sent of tx buffer
206 * Callback called after data transfer on USB line
207 *
208 * \param status UDD_EP_TRANSFER_OK, if transfer finished
209 * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
210 * \param n number of data transfered
211 */
212static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
213
214/**
215 * \brief Send buffer on line or wait a SOF event
216 *
217 * \param port Communication port number to manage
218 */
219static void udi_cdc_tx_send(uint8_t port);
220
221//@}
222
223//@}
224
225/**
226 * \name Information about configuration of communication line
227 */
228//@{
229COMPILER_WORD_ALIGNED
230static usb_cdc_line_coding_t udi_cdc_line_coding[UDI_CDC_PORT_NB];
231static bool udi_cdc_serial_state_msg_ongoing[UDI_CDC_PORT_NB];
232static volatile le16_t udi_cdc_state[UDI_CDC_PORT_NB];
233COMPILER_WORD_ALIGNED static usb_cdc_notify_serial_state_t uid_cdc_state_msg[UDI_CDC_PORT_NB];
234
235//! Status of CDC COMM interfaces
236static volatile uint8_t udi_cdc_nb_comm_enabled = 0;
237//@}
238
239/**
240 * \name Variables to manage RX/TX transfer requests
241 * Two buffers for each sense are used to optimize the speed.
242 */
243//@{
244
245//! Status of CDC DATA interfaces
246static volatile uint8_t udi_cdc_nb_data_enabled = 0;
247static volatile bool udi_cdc_data_running = false;
248//! Buffer to receive data
249COMPILER_WORD_ALIGNED static uint8_t udi_cdc_rx_buf[UDI_CDC_PORT_NB][2][UDI_CDC_RX_BUFFERS];
250//! Data available in RX buffers
251static volatile uint16_t udi_cdc_rx_buf_nb[UDI_CDC_PORT_NB][2];
252//! Give the current RX buffer used (rx0 if 0, rx1 if 1)
253static volatile uint8_t udi_cdc_rx_buf_sel[UDI_CDC_PORT_NB];
254//! Read position in current RX buffer
255static volatile uint16_t udi_cdc_rx_pos[UDI_CDC_PORT_NB];
256//! Signal a transfer on-going
257static volatile bool udi_cdc_rx_trans_ongoing[UDI_CDC_PORT_NB];
258
259//! Define a transfer halted
260#define UDI_CDC_TRANS_HALTED 2
261
262//! Buffer to send data
263COMPILER_WORD_ALIGNED static uint8_t udi_cdc_tx_buf[UDI_CDC_PORT_NB][2][UDI_CDC_TX_BUFFERS];
264//! Data available in TX buffers
265static uint16_t udi_cdc_tx_buf_nb[UDI_CDC_PORT_NB][2];
266//! Give current TX buffer used (tx0 if 0, tx1 if 1)
267static volatile uint8_t udi_cdc_tx_buf_sel[UDI_CDC_PORT_NB];
268//! Value of SOF during last TX transfer
269static uint16_t udi_cdc_tx_sof_num[UDI_CDC_PORT_NB];
270//! Signal a transfer on-going
271static volatile bool udi_cdc_tx_trans_ongoing[UDI_CDC_PORT_NB];
272//! Signal that both buffer content data to send
273static volatile bool udi_cdc_tx_both_buf_to_send[UDI_CDC_PORT_NB];
274
275//@}
276
277bool udi_cdc_comm_enable(void)
278{
279 uint8_t port;
280 uint8_t iface_comm_num;
281
282//#if UDI_CDC_PORT_NB == 1 // To optimize code
283 port = 0;
284 udi_cdc_nb_comm_enabled = 0;
285//#else
286// if (udi_cdc_nb_comm_enabled > UDI_CDC_PORT_NB) {
287// udi_cdc_nb_comm_enabled = 0;
288// }
289// port = udi_cdc_nb_comm_enabled;
290//#endif
291
292 // Initialize control signal management
293 udi_cdc_state[port] = CPU_TO_LE16(0);
294
295 uid_cdc_state_msg[port].header.bmRequestType =
296 USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS |
297 USB_REQ_RECIP_INTERFACE;
298 uid_cdc_state_msg[port].header.bNotification = USB_REQ_CDC_NOTIFY_SERIAL_STATE;
299 uid_cdc_state_msg[port].header.wValue = LE16(0);
300
301 /*
302 switch (port) {
303 #define UDI_CDC_PORT_TO_IFACE_COMM(index, unused) \
304 case index: \
305 iface_comm_num = UDI_CDC_COMM_IFACE_NUMBER_##index; \
306 break;
307 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_IFACE_COMM, ~)
308 #undef UDI_CDC_PORT_TO_IFACE_COMM
309 default:
310 iface_comm_num = UDI_CDC_COMM_IFACE_NUMBER_0;
311 break;
312 }
313 */
314 iface_comm_num = UDI_CDC_COMM_IFACE_NUMBER_0;
315
316 uid_cdc_state_msg[port].header.wIndex = LE16(iface_comm_num);
317 uid_cdc_state_msg[port].header.wLength = LE16(2);
318 uid_cdc_state_msg[port].value = CPU_TO_LE16(0);
319
320 udi_cdc_line_coding[port].dwDTERate = CPU_TO_LE32(UDI_CDC_DEFAULT_RATE);
321 udi_cdc_line_coding[port].bCharFormat = UDI_CDC_DEFAULT_STOPBITS;
322 udi_cdc_line_coding[port].bParityType = UDI_CDC_DEFAULT_PARITY;
323 udi_cdc_line_coding[port].bDataBits = UDI_CDC_DEFAULT_DATABITS;
324 // Call application callback
325 // to initialize memories or indicate that interface is enabled
326#if 0
327 UDI_CDC_SET_CODING_EXT(port,(&udi_cdc_line_coding[port]));
328 if (!UDI_CDC_ENABLE_EXT(port)) {
329 return false;
330 }
331#endif
332 udi_cdc_nb_comm_enabled++;
333 return true;
334}
335
336bool udi_cdc_data_enable(void)
337{
338 uint8_t port;
339
340//#if UDI_CDC_PORT_NB == 1 // To optimize code
341 port = 0;
342 udi_cdc_nb_data_enabled = 0;
343//#else
344// if (udi_cdc_nb_data_enabled > UDI_CDC_PORT_NB) {
345// udi_cdc_nb_data_enabled = 0;
346// }
347// port = udi_cdc_nb_data_enabled;
348//#endif
349
350 // Initialize TX management
351 udi_cdc_tx_trans_ongoing[port] = false;
352 udi_cdc_tx_both_buf_to_send[port] = false;
353 udi_cdc_tx_buf_sel[port] = 0;
354 udi_cdc_tx_buf_nb[port][0] = 0;
355 udi_cdc_tx_buf_nb[port][1] = 0;
356 udi_cdc_tx_sof_num[port] = 0;
357 udi_cdc_tx_send(port);
358
359 // Initialize RX management
360 udi_cdc_rx_trans_ongoing[port] = false;
361 udi_cdc_rx_buf_sel[port] = 0;
362 udi_cdc_rx_buf_nb[port][0] = 0;
363 udi_cdc_rx_buf_nb[port][1] = 0;
364 udi_cdc_rx_pos[port] = 0;
365 if (!udi_cdc_rx_start(port)) {
366 return false;
367 }
368 udi_cdc_nb_data_enabled++;
369 if (udi_cdc_nb_data_enabled == UDI_CDC_PORT_NB) {
370 udi_cdc_data_running = true;
371 }
372 return true;
373}
374
375void udi_cdc_comm_disable(void)
376{
377 Assert(udi_cdc_nb_comm_enabled != 0);
378 udi_cdc_nb_comm_enabled--;
379}
380
381void udi_cdc_data_disable(void)
382{
383// uint8_t port;
384
385 Assert(udi_cdc_nb_data_enabled != 0);
386 udi_cdc_nb_data_enabled--;
387// port = udi_cdc_nb_data_enabled;
388// UDI_CDC_DISABLE_EXT(port);
389 udi_cdc_data_running = false;
390}
391
392bool udi_cdc_comm_setup(void)
393{
394 uint8_t port = udi_cdc_setup_to_port();
395
396 if (Udd_setup_is_in()) {
397 // GET Interface Requests
398 if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
399 // Requests Class Interface Get
400 switch (udd_g_ctrlreq.req.bRequest) {
401 case USB_REQ_CDC_GET_LINE_CODING:
402 // Get configuration of CDC line
403 if (sizeof(usb_cdc_line_coding_t) !=
404 udd_g_ctrlreq.req.wLength)
405 return false; // Error for USB host
406 udd_g_ctrlreq.payload =
407 (uint8_t *) &
408 udi_cdc_line_coding[port];
409 udd_g_ctrlreq.payload_size =
410 sizeof(usb_cdc_line_coding_t);
411 return true;
412 }
413 }
414 }
415 if (Udd_setup_is_out()) {
416 // SET Interface Requests
417 if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
418 // Requests Class Interface Set
419 switch (udd_g_ctrlreq.req.bRequest) {
420 case USB_REQ_CDC_SET_LINE_CODING:
421 // Change configuration of CDC line
422 if (sizeof(usb_cdc_line_coding_t) !=
423 udd_g_ctrlreq.req.wLength)
424 return false; // Error for USB host
425 udd_g_ctrlreq.callback =
426 udi_cdc_line_coding_received;
427 udd_g_ctrlreq.payload =
428 (uint8_t *) &
429 udi_cdc_line_coding[port];
430 udd_g_ctrlreq.payload_size =
431 sizeof(usb_cdc_line_coding_t);
432 return true;
433 case USB_REQ_CDC_SET_CONTROL_LINE_STATE:
434 // According cdc spec 1.1 chapter 6.2.14
435// UDI_CDC_SET_DTR_EXT(port, (0 !=
436// (udd_g_ctrlreq.req.wValue
437// & CDC_CTRL_SIGNAL_DTE_PRESENT)));
438// UDI_CDC_SET_RTS_EXT(port, (0 !=
439// (udd_g_ctrlreq.req.wValue
440// & CDC_CTRL_SIGNAL_ACTIVATE_CARRIER)));
441 return true;
442 }
443 }
444 }
445 return false; // request Not supported
446}
447
448bool udi_cdc_data_setup(void)
449{
450 return false; // request Not supported
451}
452
453uint8_t udi_cdc_getsetting(void)
454{
455 return 0; // CDC don't have multiple alternate setting
456}
457
458void udi_cdc_data_sof_notify(void)
459{
460 static uint8_t port_notify = 0;
461
462 // A call of udi_cdc_data_sof_notify() is done for each port
463 udi_cdc_tx_send(port_notify);
464 /*
465#if UDI_CDC_PORT_NB != 1 // To optimize code
466 port_notify++;
467 if (port_notify >= UDI_CDC_PORT_NB) {
468 port_notify = 0;
469 }
470#endif
471 */
472}
473
474
475//-------------------------------------------------
476//------- Internal routines to control serial line
477
478static uint8_t udi_cdc_setup_to_port(void)
479{
480 uint8_t port;
481
482 /*
483 switch (udd_g_ctrlreq.req.wIndex & 0xFF) {
484#define UDI_CDC_IFACE_COMM_TO_PORT(iface, unused) \
485 case UDI_CDC_COMM_IFACE_NUMBER_##iface: \
486 port = iface; \
487 break;
488 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_IFACE_COMM_TO_PORT, ~)
489#undef UDI_CDC_IFACE_COMM_TO_PORT
490 default:
491 port = 0;
492 break;
493 }
494 */
495 port = 0;
496
497 return port;
498}
499
500static void udi_cdc_line_coding_received(void)
501{
502 uint8_t port = udi_cdc_setup_to_port();
503 UNUSED(port);
504
505// UDI_CDC_SET_CODING_EXT(port, (&udi_cdc_line_coding[port]));
506}
507
508static void udi_cdc_ctrl_state_change(uint8_t port, bool b_set, le16_t bit_mask)
509{
510 udd_ep_id_t ep_comm;
511 uint32_t irqflags; //irqflags_t
512
513
514//#if UDI_CDC_PORT_NB == 1 // To optimize code
515 port = 0;
516//#endif
517
518 // Update state
519 irqflags = __get_PRIMASK();
520 __disable_irq();
521 __DMB();
522 if (b_set) {
523 udi_cdc_state[port] |= bit_mask;
524 } else {
525 udi_cdc_state[port] &= ~(unsigned)bit_mask;
526 }
527 __DMB();
528 __set_PRIMASK(irqflags);
529
530 /*
531 // Send it if possible and state changed
532 switch (port) {
533#define UDI_CDC_PORT_TO_COMM_EP(index, unused) \
534 case index: \
535 ep_comm = UDI_CDC_COMM_EP_##index; \
536 break;
537 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_COMM_EP, ~)
538#undef UDI_CDC_PORT_TO_COMM_EP
539 default:
540 ep_comm = UDI_CDC_COMM_EP_0;
541 break;
542 }
543 */
544 ep_comm = UDI_CDC_COMM_EP_0;
545
546 udi_cdc_ctrl_state_notify(port, ep_comm);
547}
548
549
550static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep)
551{
552#if UDI_CDC_PORT_NB == 1 // To optimize code
553 port = 0;
554#endif
555
556 // Send it if possible and state changed
557 if ((!udi_cdc_serial_state_msg_ongoing[port])
558 && (udi_cdc_state[port] != uid_cdc_state_msg[port].value)) {
559 // Fill notification message
560 uid_cdc_state_msg[port].value = udi_cdc_state[port];
561 // Send notification message
562 udi_cdc_serial_state_msg_ongoing[port] =
563 udd_ep_run(ep,
564 false,
565 (uint8_t *) & uid_cdc_state_msg[port],
566 sizeof(uid_cdc_state_msg[0]),
567 udi_cdc_serial_state_msg_sent);
568 }
569}
570
571
572static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep)
573{
574 uint8_t port;
575 UNUSED(n);
576 UNUSED(status);
577
578 /*
579 switch (ep) {
580#define UDI_CDC_GET_PORT_FROM_COMM_EP(iface, unused) \
581 case UDI_CDC_COMM_EP_##iface: \
582 port = iface; \
583 break;
584 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_GET_PORT_FROM_COMM_EP, ~)
585#undef UDI_CDC_GET_PORT_FROM_COMM_EP
586 default:
587 port = 0;
588 break;
589 }
590 */
591 port = 0;
592
593 udi_cdc_serial_state_msg_ongoing[port] = false;
594
595 // For the irregular signals like break, the incoming ring signal,
596 // or the overrun error state, this will reset their values to zero
597 // and again will not send another notification until their state changes.
598 udi_cdc_state[port] &= ~(CDC_SERIAL_STATE_BREAK |
599 CDC_SERIAL_STATE_RING |
600 CDC_SERIAL_STATE_FRAMING |
601 CDC_SERIAL_STATE_PARITY | CDC_SERIAL_STATE_OVERRUN);
602 uid_cdc_state_msg[port].value &= ~(CDC_SERIAL_STATE_BREAK |
603 CDC_SERIAL_STATE_RING |
604 CDC_SERIAL_STATE_FRAMING |
605 CDC_SERIAL_STATE_PARITY | CDC_SERIAL_STATE_OVERRUN);
606 // Send it if possible and state changed
607 udi_cdc_ctrl_state_notify(port, ep);
608}
609
610//-------------------------------------------------
611//------- Internal routines to process data transfer
612
613static bool udi_cdc_rx_start(uint8_t port)
614{
615 uint32_t irqflags; //irqflags_t
616 uint8_t buf_sel_trans;
617 udd_ep_id_t ep;
618
619//#if UDI_CDC_PORT_NB == 1 // To optimize code
620 port = 0;
621//#endif
622
623 irqflags = __get_PRIMASK();
624 __disable_irq();
625 __DMB();
626 buf_sel_trans = udi_cdc_rx_buf_sel[port];
627 if (udi_cdc_rx_trans_ongoing[port] ||
628 (udi_cdc_rx_pos[port] < udi_cdc_rx_buf_nb[port][buf_sel_trans])) {
629 // Transfer already on-going or current buffer no empty
630 __DMB();
631 __set_PRIMASK(irqflags);
632 return false;
633 }
634
635 // Change current buffer
636 udi_cdc_rx_pos[port] = 0;
637 udi_cdc_rx_buf_sel[port] = (buf_sel_trans==0)?1:0;
638
639 // Start transfer on RX
640 udi_cdc_rx_trans_ongoing[port] = true;
641 __DMB();
642 __set_PRIMASK(irqflags);
643
644 if (udi_cdc_multi_is_rx_ready(port)) {
645// UDI_CDC_RX_NOTIFY(port);
646 }
647
648 /*
649 // Send the buffer with enable of short packet
650 switch (port) {
651#define UDI_CDC_PORT_TO_DATA_EP_OUT(index, unused) \
652 case index: \
653 ep = UDI_CDC_DATA_EP_OUT_##index; \
654 break;
655 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_DATA_EP_OUT, ~)
656#undef UDI_CDC_PORT_TO_DATA_EP_OUT
657 default:
658 ep = UDI_CDC_DATA_EP_OUT_0;
659 break;
660 }
661 */
662 ep = UDI_CDC_DATA_EP_OUT_0;
663
664 return udd_ep_run(ep,
665 true,
666 udi_cdc_rx_buf[port][buf_sel_trans],
667 UDI_CDC_RX_BUFFERS,
668 udi_cdc_data_received);
669}
670
671static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep)
672{
673 uint8_t buf_sel_trans;
674 uint8_t port;
675
676 /*
677 switch (ep) {
678#define UDI_CDC_DATA_EP_OUT_TO_PORT(index, unused) \
679 case UDI_CDC_DATA_EP_OUT_##index: \
680 port = index; \
681 break;
682 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DATA_EP_OUT_TO_PORT, ~)
683#undef UDI_CDC_DATA_EP_OUT_TO_PORT
684 default:
685 port = 0;
686 break;
687 }
688 */
689 port = 0;
690
691 if (UDD_EP_TRANSFER_OK != status) {
692 // Abort reception
693 return;
694 }
695
696 buf_sel_trans = (udi_cdc_rx_buf_sel[port]==0)?1:0;
697
698 if (!n) {
699 udd_ep_run( ep,
700 true,
701 udi_cdc_rx_buf[port][buf_sel_trans],
702 UDI_CDC_RX_BUFFERS,
703 udi_cdc_data_received);
704 return;
705 }
706
707 udi_cdc_rx_buf_nb[port][buf_sel_trans] = n;
708 udi_cdc_rx_trans_ongoing[port] = false;
709 udi_cdc_rx_start(port);
710}
711
712static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep)
713{
714 uint8_t port;
715 UNUSED(n);
716
717 /*
718 switch (ep) {
719#define UDI_CDC_DATA_EP_IN_TO_PORT(index, unused) \
720 case UDI_CDC_DATA_EP_IN_##index: \
721 port = index; \
722 break;
723 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DATA_EP_IN_TO_PORT, ~)
724#undef UDI_CDC_DATA_EP_IN_TO_PORT
725 default:
726 port = 0;
727 break;
728 }
729 */
730 port = 0;
731
732 if (UDD_EP_TRANSFER_OK != status) {
733 // Abort transfer
734 return;
735 }
736
737 udi_cdc_tx_buf_nb[port][(udi_cdc_tx_buf_sel[port]==0)?1:0] = 0;
738 udi_cdc_tx_both_buf_to_send[port] = false;
739 udi_cdc_tx_trans_ongoing[port] = false;
740
741 if (n != 0) {
742 UDI_CDC_TX_EMPTY_NOTIFY(port);
743 }
744
745 udi_cdc_tx_send(port);
746}
747
748static void udi_cdc_tx_send(uint8_t port)
749{
750 uint32_t irqflags; //irqflags_t
751 uint8_t buf_sel_trans;
752 bool b_short_packet;
753 udd_ep_id_t ep;
754 static uint16_t sof_zlp_counter = 0;
755
756//#if UDI_CDC_PORT_NB == 1 // To optimize code
757 port = 0;
758//#endif
759
760 if (udi_cdc_tx_trans_ongoing[port]) {
761 return; // Already on going or wait next SOF to send next data
762 }
763 if (udd_is_high_speed()) {
764 if (udi_cdc_tx_sof_num[port] == udd_get_micro_frame_number()) {
765 return; // Wait next SOF to send next data
766 }
767 }else{
768 if (udi_cdc_tx_sof_num[port] == udd_get_frame_number()) {
769 return; // Wait next SOF to send next data
770 }
771 }
772
773 irqflags = __get_PRIMASK();
774 __disable_irq();
775 __DMB();
776 buf_sel_trans = udi_cdc_tx_buf_sel[port];
777 if (udi_cdc_tx_buf_nb[port][buf_sel_trans] == 0) {
778 sof_zlp_counter++;
779 if (((!udd_is_high_speed()) && (sof_zlp_counter < 100))
780 || (udd_is_high_speed() && (sof_zlp_counter < 800))) {
781 __DMB();
782 __set_PRIMASK(irqflags);
783 return;
784 }
785 }
786 sof_zlp_counter = 0;
787
788 if (!udi_cdc_tx_both_buf_to_send[port]) {
789 // Send current Buffer
790 // and switch the current buffer
791 udi_cdc_tx_buf_sel[port] = (buf_sel_trans==0)?1:0;
792 }else{
793 // Send the other Buffer
794 // and no switch the current buffer
795 buf_sel_trans = (buf_sel_trans==0)?1:0;
796 }
797 udi_cdc_tx_trans_ongoing[port] = true;
798 __DMB();
799 __set_PRIMASK(irqflags);
800
801 b_short_packet = (udi_cdc_tx_buf_nb[port][buf_sel_trans] != UDI_CDC_TX_BUFFERS);
802 if (b_short_packet) {
803 if (udd_is_high_speed()) {
804 udi_cdc_tx_sof_num[port] = udd_get_micro_frame_number();
805 }else{
806 udi_cdc_tx_sof_num[port] = udd_get_frame_number();
807 }
808 }else{
809 udi_cdc_tx_sof_num[port] = 0; // Force next transfer without wait SOF
810 }
811
812 /*
813 // Send the buffer with enable of short packet
814 switch (port) {
815#define UDI_CDC_PORT_TO_DATA_EP_IN(index, unused) \
816 case index: \
817 ep = UDI_CDC_DATA_EP_IN_##index; \
818 break;
819 MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_DATA_EP_IN, ~)
820#undef UDI_CDC_PORT_TO_DATA_EP_IN
821 default:
822 ep = UDI_CDC_DATA_EP_IN_0;
823 break;
824 }
825 */
826 ep = UDI_CDC_DATA_EP_IN_0;
827
828 udd_ep_run( ep,
829 b_short_packet,
830 udi_cdc_tx_buf[port][buf_sel_trans],
831 udi_cdc_tx_buf_nb[port][buf_sel_trans],
832 udi_cdc_data_sent);
833}
834
835//---------------------------------------------
836//------- Application interface
837
838void udi_cdc_ctrl_signal_dcd(bool b_set)
839{
840 udi_cdc_ctrl_state_change(0, b_set, CDC_SERIAL_STATE_DCD);
841}
842
843void udi_cdc_ctrl_signal_dsr(bool b_set)
844{
845 udi_cdc_ctrl_state_change(0, b_set, CDC_SERIAL_STATE_DSR);
846}
847
848void udi_cdc_signal_framing_error(void)
849{
850 udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_FRAMING);
851}
852
853void udi_cdc_signal_parity_error(void)
854{
855 udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_PARITY);
856}
857
858void udi_cdc_signal_overrun(void)
859{
860 udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_OVERRUN);
861}
862
863void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set)
864{
865 udi_cdc_ctrl_state_change(port, b_set, CDC_SERIAL_STATE_DCD);
866}
867
868void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set)
869{
870 udi_cdc_ctrl_state_change(port, b_set, CDC_SERIAL_STATE_DSR);
871}
872
873void udi_cdc_multi_signal_framing_error(uint8_t port)
874{
875 udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_FRAMING);
876}
877
878void udi_cdc_multi_signal_parity_error(uint8_t port)
879{
880 udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_PARITY);
881}
882
883void udi_cdc_multi_signal_overrun(uint8_t port)
884{
885 udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_OVERRUN);
886}
887
888iram_size_t udi_cdc_multi_get_nb_received_data(uint8_t port)
889{
890 uint32_t irqflags; //irqflags_t
891 uint16_t pos;
892 iram_size_t nb_received;
893
894//#if UDI_CDC_PORT_NB == 1 // To optimize code
895 port = 0;
896//#endif
897
898 irqflags = __get_PRIMASK();
899 __disable_irq();
900 __DMB();
901 pos = udi_cdc_rx_pos[port];
902 nb_received = udi_cdc_rx_buf_nb[port][udi_cdc_rx_buf_sel[port]] - pos;
903 __DMB();
904 __set_PRIMASK(irqflags);
905 return nb_received;
906}
907
908iram_size_t udi_cdc_get_nb_received_data(void)
909{
910 return udi_cdc_multi_get_nb_received_data(0);
911}
912
913bool udi_cdc_multi_is_rx_ready(uint8_t port)
914{
915 return (udi_cdc_multi_get_nb_received_data(port) > 0);
916}
917
918bool udi_cdc_is_rx_ready(void)
919{
920 return udi_cdc_multi_is_rx_ready(0);
921}
922
923int udi_cdc_multi_getc(uint8_t port)
924{
925 uint32_t irqflags; //irqflags_t
926 int rx_data = 0;
927 bool b_databit_9;
928 uint16_t pos;
929 uint8_t buf_sel;
930 bool again;
931
932//#if UDI_CDC_PORT_NB == 1 // To optimize code
933 port = 0;
934//#endif
935
936 b_databit_9 = (9 == udi_cdc_line_coding[port].bDataBits);
937
938udi_cdc_getc_process_one_byte:
939 // Check available data
940 irqflags = __get_PRIMASK();
941 __disable_irq();
942 __DMB();
943 pos = udi_cdc_rx_pos[port];
944 buf_sel = udi_cdc_rx_buf_sel[port];
945 again = pos >= udi_cdc_rx_buf_nb[port][buf_sel];
946 __DMB();
947 __set_PRIMASK(irqflags);
948 while (again) {
949 if (!udi_cdc_data_running) {
950 return 0;
951 }
952 goto udi_cdc_getc_process_one_byte;
953 }
954
955 // Read data
956 rx_data |= udi_cdc_rx_buf[port][buf_sel][pos];
957 udi_cdc_rx_pos[port] = pos+1;
958
959 udi_cdc_rx_start(port);
960
961 if (b_databit_9) {
962 // Receive MSB
963 b_databit_9 = false;
964 rx_data = rx_data << 8;
965 goto udi_cdc_getc_process_one_byte;
966 }
967 return rx_data;
968}
969
970int udi_cdc_getc(void)
971{
972 return udi_cdc_multi_getc(0);
973}
974
975iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size)
976{
977 uint32_t irqflags; //irqflags_t
978 uint8_t *ptr_buf = (uint8_t *)buf;
979 iram_size_t copy_nb;
980 uint16_t pos;
981 uint8_t buf_sel;
982 bool again;
983
984//#if UDI_CDC_PORT_NB == 1 // To optimize code
985 port = 0;
986//#endif
987
988udi_cdc_read_buf_loop_wait:
989 // Check available data
990 irqflags = __get_PRIMASK();
991 __disable_irq();
992 __DMB(); pos = udi_cdc_rx_pos[port];
993 buf_sel = udi_cdc_rx_buf_sel[port];
994 again = pos >= udi_cdc_rx_buf_nb[port][buf_sel];
995 __DMB();
996 __set_PRIMASK(irqflags);
997 while (again) {
998 if (!udi_cdc_data_running) {
999 return size;
1000 }
1001 goto udi_cdc_read_buf_loop_wait;
1002 }
1003
1004 // Read data
1005 copy_nb = udi_cdc_rx_buf_nb[port][buf_sel] - pos;
1006 if (copy_nb>size) {
1007 copy_nb = size;
1008 }
1009 memcpy(ptr_buf, &udi_cdc_rx_buf[port][buf_sel][pos], copy_nb);
1010 udi_cdc_rx_pos[port] += copy_nb;
1011 ptr_buf += copy_nb;
1012 size -= copy_nb;
1013 udi_cdc_rx_start(port);
1014
1015 if (size) {
1016 goto udi_cdc_read_buf_loop_wait;
1017 }
1018 return 0;
1019}
1020
1021static iram_size_t udi_cdc_multi_read_no_polling(uint8_t port, void* buf, iram_size_t size)
1022{
1023 uint8_t *ptr_buf = (uint8_t *)buf;
1024 iram_size_t nb_avail_data;
1025 uint16_t pos;
1026 uint8_t buf_sel;
1027 uint32_t irqflags; //irqflags_t
1028
1029//#if UDI_CDC_PORT_NB == 1 // To optimize code
1030 port = 0;
1031//#endif
1032
1033 //Data interface not started... exit
1034 if (!udi_cdc_data_running) {
1035 return 0;
1036 }
1037
1038 //Get number of available data
1039 // Check available data
1040 irqflags = __get_PRIMASK();
1041 __disable_irq();
1042 __DMB();
1043 pos = udi_cdc_rx_pos[port];
1044 buf_sel = udi_cdc_rx_buf_sel[port];
1045 nb_avail_data = udi_cdc_rx_buf_nb[port][buf_sel] - pos;
1046 __DMB();
1047 __set_PRIMASK(irqflags);
1048 //If the buffer contains less than the requested number of data,
1049 //adjust read size
1050 if(nb_avail_data<size) {
1051 size = nb_avail_data;
1052 }
1053 if(size>0) {
1054 memcpy(ptr_buf, &udi_cdc_rx_buf[port][buf_sel][pos], size);
1055 irqflags = __get_PRIMASK();
1056 __disable_irq();
1057 __DMB();
1058 udi_cdc_rx_pos[port] += size;
1059 __DMB();
1060 __set_PRIMASK(irqflags);
1061 ptr_buf += size;
1062 udi_cdc_rx_start(port);
1063 }
1064 return(nb_avail_data);
1065}
1066
1067iram_size_t udi_cdc_read_no_polling(void* buf, iram_size_t size)
1068{
1069 return udi_cdc_multi_read_no_polling(0, buf, size);
1070}
1071
1072iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size)
1073{
1074 return udi_cdc_multi_read_buf(0, buf, size);
1075}
1076
1077iram_size_t udi_cdc_multi_get_free_tx_buffer(uint8_t port)
1078{
1079 uint32_t irqflags; //irqflags_t
1080 iram_size_t buf_sel_nb, retval;
1081 uint8_t buf_sel;
1082
1083//#if UDI_CDC_PORT_NB == 1 // To optimize code
1084 port = 0;
1085//#endif
1086
1087 irqflags = __get_PRIMASK();
1088 __disable_irq();
1089 __DMB();
1090 buf_sel = udi_cdc_tx_buf_sel[port];
1091 buf_sel_nb = udi_cdc_tx_buf_nb[port][buf_sel];
1092 if (buf_sel_nb == UDI_CDC_TX_BUFFERS) {
1093 if ((!udi_cdc_tx_trans_ongoing[port])
1094 && (!udi_cdc_tx_both_buf_to_send[port])) {
1095 /* One buffer is full, but the other buffer is not used.
1096 * (not used = transfer on-going)
1097 * then move to the other buffer to store data */
1098 udi_cdc_tx_both_buf_to_send[port] = true;
1099 udi_cdc_tx_buf_sel[port] = (buf_sel == 0)? 1 : 0;
1100 buf_sel_nb = 0;
1101 }
1102 }
1103 retval = UDI_CDC_TX_BUFFERS - buf_sel_nb;
1104 __DMB();
1105 __set_PRIMASK(irqflags);
1106 return retval;
1107}
1108
1109iram_size_t udi_cdc_get_free_tx_buffer(void)
1110{
1111 return udi_cdc_multi_get_free_tx_buffer(0);
1112}
1113
1114bool udi_cdc_multi_is_tx_ready(uint8_t port)
1115{
1116 return (udi_cdc_multi_get_free_tx_buffer(port) != 0);
1117}
1118
1119bool udi_cdc_is_tx_ready(void)
1120{
1121 return udi_cdc_multi_is_tx_ready(0);
1122}
1123
1124int udi_cdc_multi_putc(uint8_t port, int value)
1125{
1126 uint32_t irqflags; //irqflags_t
1127 bool b_databit_9;
1128 uint8_t buf_sel;
1129
1130//#if UDI_CDC_PORT_NB == 1 // To optimize code
1131 port = 0;
1132//#endif
1133
1134 b_databit_9 = (9 == udi_cdc_line_coding[port].bDataBits);
1135
1136udi_cdc_putc_process_one_byte:
1137 // Check available space
1138 if (!udi_cdc_multi_is_tx_ready(port)) {
1139 if (!udi_cdc_data_running) {
1140 return false;
1141 }
1142 goto udi_cdc_putc_process_one_byte;
1143 }
1144
1145 // Write value
1146 irqflags = __get_PRIMASK();
1147 __disable_irq();
1148 __DMB();
1149 buf_sel = udi_cdc_tx_buf_sel[port];
1150 udi_cdc_tx_buf[port][buf_sel][udi_cdc_tx_buf_nb[port][buf_sel]++] = value;
1151 __DMB();
1152 __set_PRIMASK(irqflags);
1153
1154 if (b_databit_9) {
1155 // Send MSB
1156 b_databit_9 = false;
1157 value = value >> 8;
1158 goto udi_cdc_putc_process_one_byte;
1159 }
1160 return true;
1161}
1162
1163int udi_cdc_putc(int value)
1164{
1165 return udi_cdc_multi_putc(0, value);
1166}
1167
1168iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size)
1169{
1170 uint32_t irqflags; //irqflags_t
1171 uint8_t buf_sel;
1172 uint16_t buf_nb;
1173 iram_size_t copy_nb;
1174 uint8_t *ptr_buf = (uint8_t *)buf;
1175
1176//#if UDI_CDC_PORT_NB == 1 // To optimize code
1177 port = 0;
1178//#endif
1179
1180 if (9 == udi_cdc_line_coding[port].bDataBits) {
1181 size *=2;
1182 }
1183
1184 udi_cdc_write_buf_loop_wait:
1185
1186 // Check available space
1187 if (!udi_cdc_multi_is_tx_ready(port)) {
1188 if (!udi_cdc_data_running) {
1189 return size;
1190 }
1191 goto udi_cdc_write_buf_loop_wait;
1192 }
1193
1194 // Write values
1195 irqflags = __get_PRIMASK();
1196 __disable_irq();
1197 __DMB();
1198 buf_sel = udi_cdc_tx_buf_sel[port];
1199 buf_nb = udi_cdc_tx_buf_nb[port][buf_sel];
1200 copy_nb = UDI_CDC_TX_BUFFERS - buf_nb;
1201 if (copy_nb > size) {
1202 copy_nb = size;
1203 }
1204 memcpy(&udi_cdc_tx_buf[port][buf_sel][buf_nb], ptr_buf, copy_nb);
1205 udi_cdc_tx_buf_nb[port][buf_sel] = buf_nb + copy_nb;
1206 __DMB();
1207 __set_PRIMASK(irqflags);
1208
1209 // Update buffer pointer
1210 ptr_buf = ptr_buf + copy_nb;
1211 size -= copy_nb;
1212
1213 if (size) {
1214 goto udi_cdc_write_buf_loop_wait;
1215 }
1216
1217 return 0;
1218}
1219
1220iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size)
1221{
1222 return udi_cdc_multi_write_buf(0, buf, size);
1223}
1224
1225#define MAX_PRINT 256
1226#define CDC_SEND_INTERVAL 2
1227uint32_t cdc_tx_send_time_next;
1228
1229void CDC_send(void)
1230{
1231 while (CLK_get_ms() < cdc_tx_send_time_next);
1232 udi_cdc_tx_send(0);
1233 cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL;
1234}
1235
1236uint32_t CDC_print(char *printbuf)
1237{
1238 uint32_t count=0;
1239 char *buf = printbuf;
1240 char c;
1241
1242 if (CLK_get_ms() < 5000) return 0;
1243
1244 while ((c = *buf++) != 0 && !(count >= MAX_PRINT))
1245 {
1246 count++;
1247 if (!udi_cdc_is_tx_ready()) return 0;
1248 udi_cdc_putc(c);
1249 if (count >= UDI_CDC_TX_BUFFERS)
1250 {
1251 count = 0;
1252 CDC_send();
1253 }
1254 }
1255 if (count)
1256 {
1257 CDC_send();
1258 }
1259 return 1;
1260}
1261
1262
1263char printbuf[CDC_PRINTBUF_SIZE];
1264
1265int dpf(const char *_Format, ...)
1266{
1267 va_list va; //Variable argument list variable
1268 int result;
1269
1270 va_start(va,_Format); //Initialize the variable argument list
1271 result = vspf(printbuf, _Format, va);
1272 va_end(va);
1273
1274 CDC_print(printbuf);
1275
1276 return result;
1277}
1278
1279//global "inbuf" if desired
1280inbuf_t inbuf;
1281
1282uint32_t CDC_input_buf(inbuf_t inbuf, uint32_t inbuf_size)
1283{
1284 int RXChar;
1285 int entered = 0;
1286
1287 if (!udi_cdc_is_rx_ready()) return 0;
1288 udi_cdc_get_nb_received_data();
1289 RXChar = udi_cdc_getc();
1290
1291 if (RXChar)
1292 {
1293 switch (RXChar)
1294 {
1295 case '\t': //tab - repeat last
1296 inbuf.count=inbuf.lastcount;
1297 inbuf.buf[inbuf.count+1] = 0;
1298 CDC_print(inbuf.buf);
1299 break;
1300 case '\r': //enter
1301 inbuf.buf[inbuf.count]=0;
1302 inbuf.lastcount = inbuf.count;
1303 inbuf.count = 0;
1304 entered = 1;
1305 break;
1306 case '\b': //backspace
1307 if (inbuf.count > 0) {
1308 inbuf.count -= 1;
1309 CDC_print("\b \b\0");
1310 }
1311 else
1312 CDC_print("\a\0");
1313 break;
1314 default:
1315 if ((RXChar >= 32) && (RXChar <= 126))
1316 {
1317 if (inbuf.count < inbuf_size-1)
1318 {
1319 inbuf.buf[inbuf.count] = RXChar;
1320 inbuf.buf[inbuf.count+1] = 0;
1321 CDC_print(&inbuf.buf[inbuf.count]);
1322 inbuf.count += 1;
1323 }
1324 else
1325 CDC_print("\a\0");
1326 }
1327 break;
1328 }
1329 RXChar = 0;
1330 }
1331 return entered;
1332}
1333
1334uint32_t CDC_input()
1335{
1336 return CDC_input_buf(inbuf, CDC_INBUF_SIZE);
1337}
1338
1339void CDC_init(void)
1340{
1341 inbuf.count = 0;
1342 inbuf.lastcount = 0;
1343 printbuf[0] = 0;
1344 cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL;
1345}
1346
1347#else //CDC line 62
1348
1349char printbuf[CDC_PRINTBUF_SIZE];
1350
1351void CDC_send(void)
1352{
1353 return;
1354}
1355
1356uint32_t CDC_print(char *printbuf)
1357{
1358 return 0;
1359}
1360
1361int dpf(const char *_Format, ...)
1362{
1363 return 0;
1364}
1365
1366inbuf_t inbuf;
1367
1368uint32_t CDC_input(void)
1369{
1370 return 0;
1371}
1372
1373void CDC_init(void)
1374{
1375 inbuf.count = 0;
1376 inbuf.lastcount = 0;
1377 printbuf[0]=0;
1378}
1379
1380char printbuf[CDC_PRINTBUF_SIZE];
1381
1382#endif //CDC line 62
1383
1384//@}
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc.h b/tmk_core/protocol/arm_atsam/usb/udi_cdc.h
new file mode 100644
index 000000000..6b70e96d0
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc.h
@@ -0,0 +1,381 @@
1/**
2 * \file
3 *
4 * \brief USB Device Communication Device Class (CDC) interface definitions.
5 *
6 * Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDI_CDC_H_
48#define _UDI_CDC_H_
49
50#ifdef CDC
51
52#include "conf_usb.h"
53#include "usb_protocol.h"
54#include "usb_protocol_cdc.h"
55#include "udd.h"
56#include "udc_desc.h"
57#include "udi.h"
58
59// Check the number of port
60#ifndef UDI_CDC_PORT_NB
61# define UDI_CDC_PORT_NB 1
62#endif
63#if (UDI_CDC_PORT_NB > 1)
64# error UDI_CDC_PORT_NB must be at most 1
65#endif
66
67#ifdef __cplusplus
68extern "C" {
69#endif
70
71/**
72 * \addtogroup udi_cdc_group_udc
73 * @{
74 */
75
76//! Global structure which contains standard UDI API for UDC
77extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm;
78extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_data;
79//@}
80
81//#define CDC_ACM_SIZE 64 see usb_protocol_cdc.h
82//#define CDC_RX_SIZE 64
83
84//! CDC communication endpoints size for all speeds
85#define UDI_CDC_COMM_EP_SIZE CDC_ACM_SIZE
86//! CDC data endpoints size for FS speed (8B, 16B, 32B, 64B)
87#define UDI_CDC_DATA_EPS_FS_SIZE CDC_RX_SIZE
88
89#define CDC_PRINT_BUF_SIZE 256
90extern char printbuf[CDC_PRINT_BUF_SIZE];
91
92//@}
93
94/**
95 * \ingroup udi_group
96 * \defgroup udi_cdc_group USB Device Interface (UDI) for Communication Class Device (CDC)
97 *
98 * Common APIs used by high level application to use this USB class.
99 *
100 * These routines are used to transfer and control data
101 * to/from USB CDC endpoint.
102 *
103 * See \ref udi_cdc_quickstart.
104 * @{
105 */
106
107/**
108 * \name Interface for application with single CDC interface support
109 */
110//@{
111
112/**
113 * \brief Notify a state change of DCD signal
114 *
115 * \param b_set DCD is enabled if true, else disabled
116 */
117void udi_cdc_ctrl_signal_dcd(bool b_set);
118
119/**
120 * \brief Notify a state change of DSR signal
121 *
122 * \param b_set DSR is enabled if true, else disabled
123 */
124void udi_cdc_ctrl_signal_dsr(bool b_set);
125
126/**
127 * \brief Notify a framing error
128 */
129void udi_cdc_signal_framing_error(void);
130
131/**
132 * \brief Notify a parity error
133 */
134void udi_cdc_signal_parity_error(void);
135
136/**
137 * \brief Notify a overrun
138 */
139void udi_cdc_signal_overrun(void);
140
141/**
142 * \brief Gets the number of byte received
143 *
144 * \return the number of data available
145 */
146iram_size_t udi_cdc_get_nb_received_data(void);
147
148/**
149 * \brief This function checks if a character has been received on the CDC line
150 *
151 * \return \c 1 if a byte is ready to be read.
152 */
153bool udi_cdc_is_rx_ready(void);
154
155/**
156 * \brief Waits and gets a value on CDC line
157 *
158 * \return value read on CDC line
159 */
160int udi_cdc_getc(void);
161
162/**
163 * \brief Reads a RAM buffer on CDC line
164 *
165 * \param buf Values read
166 * \param size Number of value read
167 *
168 * \return the number of data remaining
169 */
170iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size);
171
172/**
173 * \brief Non polling reads of a up to 'size' data from CDC line
174 *
175 * \param port Communication port number to manage
176 * \param buf Buffer where to store read data
177 * \param size Maximum number of data to read (size of buffer)
178 *
179 * \return the number of data effectively read
180 */
181iram_size_t udi_cdc_read_no_polling(void* buf, iram_size_t size);
182
183/**
184 * \brief Gets the number of free byte in TX buffer
185 *
186 * \return the number of free byte in TX buffer
187 */
188iram_size_t udi_cdc_get_free_tx_buffer(void);
189
190/**
191 * \brief This function checks if a new character sent is possible
192 * The type int is used to support scanf redirection from compiler LIB.
193 *
194 * \return \c 1 if a new character can be sent
195 */
196bool udi_cdc_is_tx_ready(void);
197
198/**
199 * \brief Puts a byte on CDC line
200 * The type int is used to support printf redirection from compiler LIB.
201 *
202 * \param value Value to put
203 *
204 * \return \c 1 if function was successfully done, otherwise \c 0.
205 */
206int udi_cdc_putc(int value);
207
208/**
209 * \brief Writes a RAM buffer on CDC line
210 *
211 * \param buf Values to write
212 * \param size Number of value to write
213 *
214 * \return the number of data remaining
215 */
216iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size);
217//@}
218
219/**
220 * \name Interface for application with multi CDC interfaces support
221 */
222//@{
223
224/**
225 * \brief Notify a state change of DCD signal
226 *
227 * \param port Communication port number to manage
228 * \param b_set DCD is enabled if true, else disabled
229 */
230void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set);
231
232/**
233 * \brief Notify a state change of DSR signal
234 *
235 * \param port Communication port number to manage
236 * \param b_set DSR is enabled if true, else disabled
237 */
238void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set);
239
240/**
241 * \brief Notify a framing error
242 *
243 * \param port Communication port number to manage
244 */
245void udi_cdc_multi_signal_framing_error(uint8_t port);
246
247/**
248 * \brief Notify a parity error
249 *
250 * \param port Communication port number to manage
251 */
252void udi_cdc_multi_signal_parity_error(uint8_t port);
253
254/**
255 * \brief Notify a overrun
256 *
257 * \param port Communication port number to manage
258 */
259void udi_cdc_multi_signal_overrun(uint8_t port);
260
261/**
262 * \brief Gets the number of byte received
263 *
264 * \param port Communication port number to manage
265 *
266 * \return the number of data available
267 */
268iram_size_t udi_cdc_multi_get_nb_received_data(uint8_t port);
269
270/**
271 * \brief This function checks if a character has been received on the CDC line
272 *
273 * \param port Communication port number to manage
274 *
275 * \return \c 1 if a byte is ready to be read.
276 */
277bool udi_cdc_multi_is_rx_ready(uint8_t port);
278
279/**
280 * \brief Waits and gets a value on CDC line
281 *
282 * \param port Communication port number to manage
283 *
284 * \return value read on CDC line
285 */
286int udi_cdc_multi_getc(uint8_t port);
287
288/**
289 * \brief Reads a RAM buffer on CDC line
290 *
291 * \param port Communication port number to manage
292 * \param buf Values read
293 * \param size Number of values read
294 *
295 * \return the number of data remaining
296 */
297iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size);
298
299/**
300 * \brief Gets the number of free byte in TX buffer
301 *
302 * \param port Communication port number to manage
303 *
304 * \return the number of free byte in TX buffer
305 */
306iram_size_t udi_cdc_multi_get_free_tx_buffer(uint8_t port);
307
308/**
309 * \brief This function checks if a new character sent is possible
310 * The type int is used to support scanf redirection from compiler LIB.
311 *
312 * \param port Communication port number to manage
313 *
314 * \return \c 1 if a new character can be sent
315 */
316bool udi_cdc_multi_is_tx_ready(uint8_t port);
317
318/**
319 * \brief Puts a byte on CDC line
320 * The type int is used to support printf redirection from compiler LIB.
321 *
322 * \param port Communication port number to manage
323 * \param value Value to put
324 *
325 * \return \c 1 if function was successfully done, otherwise \c 0.
326 */
327int udi_cdc_multi_putc(uint8_t port, int value);
328
329/**
330 * \brief Writes a RAM buffer on CDC line
331 *
332 * \param port Communication port number to manage
333 * \param buf Values to write
334 * \param size Number of value to write
335 *
336 * \return the number of data remaining
337 */
338iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size);
339//@}
340
341#define CDC_PRINTBUF_SIZE 256
342extern char printbuf[CDC_PRINTBUF_SIZE];
343
344#define CDC_INBUF_SIZE 256
345
346typedef struct {
347 uint32_t count;
348 uint32_t lastcount;
349 char buf[CDC_INBUF_SIZE];
350} inbuf_t;
351
352#else //CDC
353
354// keep these to accommodate calls if remaining
355#define CDC_PRINTBUF_SIZE 1
356extern char printbuf[CDC_PRINTBUF_SIZE];
357
358#define CDC_INBUF_SIZE 1
359
360typedef struct {
361 uint32_t count;
362 uint32_t lastcount;
363 char buf[CDC_INBUF_SIZE];
364} inbuf_t;
365
366extern inbuf_t inbuf;
367
368#endif //CDC
369
370uint32_t CDC_print(char *printbuf);
371uint32_t CDC_input(void);
372void CDC_init(void);
373
374#define __xprintf dpf
375int dpf(const char *_Format, ...);
376
377#ifdef __cplusplus
378}
379#endif
380
381#endif // _UDI_CDC_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h b/tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h
new file mode 100644
index 000000000..2db61fab5
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h
@@ -0,0 +1,72 @@
1/**
2 * \file
3 *
4 * \brief Default CDC configuration for a USB Device with a single interface
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDI_CDC_CONF_H_
48#define _UDI_CDC_CONF_H_
49
50#include "usb_protocol_cdc.h"
51#include "conf_usb.h"
52#include "udi_device_conf.h"
53
54#ifndef UDI_CDC_PORT_NB
55#define UDI_CDC_PORT_NB 1
56#endif
57
58#ifdef __cplusplus
59extern "C" {
60#endif
61
62#define UDI_CDC_DATA_EP_IN_0 ((CDC_TX_ENDPOINT) | (USB_EP_DIR_IN)) //TX
63#define UDI_CDC_DATA_EP_OUT_0 ((CDC_RX_ENDPOINT) | (USB_EP_DIR_OUT)) // RX
64#define UDI_CDC_COMM_EP_0 ((CDC_ACM_ENDPOINT) | (USB_EP_DIR_IN)) // Notify endpoint
65
66#define UDI_CDC_COMM_IFACE_NUMBER_0 (CDC_STATUS_INTERFACE)
67#define UDI_CDC_DATA_IFACE_NUMBER_0 (CDC_DATA_INTERFACE)
68
69#ifdef __cplusplus
70}
71#endif
72#endif // _UDI_CDC_CONF_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h
new file mode 100644
index 000000000..c78726234
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h
@@ -0,0 +1,715 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _UDI_DEVICE_CONF_H_
19#define _UDI_DEVICE_CONF_H_
20
21#include "udi_device_epsize.h"
22#include "usb_protocol.h"
23#include "compiler.h"
24#include "usb_protocol_hid.h"
25
26#define DEVICE_CLASS 0
27#define DEVICE_SUBCLASS 0
28#define DEVICE_PROTOCOL 0
29
30#define KBD
31
32//#define MOUSE_ENABLE //rules.mk
33#ifdef MOUSE_ENABLE
34#define MOU
35#endif
36
37//#define EXTRAKEY_ENABLE //rules.mk
38#ifdef EXTRAKEY_ENABLE
39#define EXK
40#endif
41
42//#define RAW_ENABLE //rules.mk
43#ifdef RAW_ENABLE
44#define RAW
45#endif
46
47//#define CONSOLE_ENABLE //deferred implementation
48//#ifdef CONSOLE_ENABLE
49//#define CON
50//#endif
51
52//#define NKRO_ENABLE //rules.mk
53#ifdef NKRO_ENABLE
54#define NKRO
55#endif
56
57//#define MIDI_ENABLE //deferred implementation
58//#ifdef MIDI_ENABLE
59//#define MIDI
60//#endif
61
62//#define VIRTSER_ENABLE //rules.mk
63#ifdef VIRTSER_ENABLE
64#define CDC
65//because CDC uses IAD (interface association descriptor
66//per USB Interface Association Descriptor Device Class Code and Use Model 7/23/2003 Rev 1.0)
67#undef DEVICE_CLASS
68#define DEVICE_CLASS 0xEF
69#undef DEVICE_SUBCLASS
70#define DEVICE_SUBCLASS 0x02
71#undef DEVICE_PROTOCOL
72#define DEVICE_PROTOCOL 0x01
73#endif
74
75/* number of interfaces */
76#define NEXT_INTERFACE_0 0
77
78#ifdef KBD
79#define KEYBOARD_INTERFACE NEXT_INTERFACE_0
80#define NEXT_INTERFACE_1 (KEYBOARD_INTERFACE + 1)
81#define UDI_HID_KBD_IFACE_NUMBER KEYBOARD_INTERFACE
82#else
83#define NEXT_INTERFACE_1 NEXT_INTERFACE_0
84#endif
85
86// It is important that the Raw HID interface is at a constant
87// interface number, to support Linux/OSX platforms and chrome.hid
88// If Raw HID is enabled, let it be always 1.
89#ifdef RAW
90#define RAW_INTERFACE NEXT_INTERFACE_1
91#define NEXT_INTERFACE_2 (RAW_INTERFACE + 1)
92#else
93#define NEXT_INTERFACE_2 NEXT_INTERFACE_1
94#endif
95
96#ifdef MOU
97#define MOUSE_INTERFACE NEXT_INTERFACE_2
98#define UDI_HID_MOU_IFACE_NUMBER MOUSE_INTERFACE
99#define NEXT_INTERFACE_3 (MOUSE_INTERFACE + 1)
100#else
101#define NEXT_INTERFACE_3 NEXT_INTERFACE_2
102#endif
103
104#ifdef EXK
105#define EXTRAKEY_INTERFACE NEXT_INTERFACE_3
106#define NEXT_INTERFACE_4 (EXTRAKEY_INTERFACE + 1)
107#define UDI_HID_EXK_IFACE_NUMBER EXTRAKEY_INTERFACE
108#else
109#define NEXT_INTERFACE_4 NEXT_INTERFACE_3
110#endif
111
112#ifdef CON
113#define CONSOLE_INTERFACE NEXT_INTERFACE_4
114#define NEXT_INTERFACE_5 (CONSOLE_INTERFACE + 1)
115#else
116#define NEXT_INTERFACE_5 NEXT_INTERFACE_4
117#endif
118
119#ifdef NKRO
120#define NKRO_INTERFACE NEXT_INTERFACE_5
121#define NEXT_INTERFACE_6 (NKRO_INTERFACE + 1)
122#define UDI_HID_NKRO_IFACE_NUMBER NKRO_INTERFACE
123#else
124#define NEXT_INTERFACE_6 NEXT_INTERFACE_5
125#endif
126
127#ifdef MIDI
128#define AC_INTERFACE NEXT_INTERFACE_6
129#define AS_INTERFACE (AC_INTERFACE + 1)
130#define NEXT_INTERFACE_7 (AS_INTERFACE + 1)
131#else
132#define NEXT_INTERFACE_7 NEXT_INTERFACE_6
133#endif
134
135#ifdef CDC
136#define CCI_INTERFACE NEXT_INTERFACE_7
137#define CDI_INTERFACE (CCI_INTERFACE + 1)
138#define NEXT_INTERFACE_8 (CDI_INTERFACE + 1)
139#define CDC_STATUS_INTERFACE CCI_INTERFACE
140#define CDC_DATA_INTERFACE CDI_INTERFACE
141#else
142#define NEXT_INTERFACE_8 NEXT_INTERFACE_7
143#endif
144
145/* nubmer of interfaces */
146#define TOTAL_INTERFACES NEXT_INTERFACE_8
147#define USB_DEVICE_NB_INTERFACE TOTAL_INTERFACES
148
149
150// **********************************************************************
151// Endopoint number and size
152// **********************************************************************
153#define USB_DEVICE_EP_CTRL_SIZE 8
154
155#define NEXT_IN_EPNUM_0 1
156#define NEXT_OUT_EPNUM_0 1
157
158#ifdef KBD
159#define KEYBOARD_IN_EPNUM NEXT_IN_EPNUM_0
160#define UDI_HID_KBD_EP_IN KEYBOARD_IN_EPNUM
161#define NEXT_IN_EPNUM_1 (KEYBOARD_IN_EPNUM + 1)
162#define UDI_HID_KBD_EP_SIZE KEYBOARD_EPSIZE
163#define KBD_POLLING_INTERVAL 10
164#ifndef UDI_HID_KBD_STRING_ID
165#define UDI_HID_KBD_STRING_ID 0
166#endif
167#else
168#define NEXT_IN_EPNUM_1 NEXT_IN_EPNUM_0
169#endif
170
171#ifdef MOU
172#define MOUSE_IN_EPNUM NEXT_IN_EPNUM_1
173#define NEXT_IN_EPNUM_2 (MOUSE_IN_EPNUM + 1)
174#define UDI_HID_MOU_EP_IN MOUSE_IN_EPNUM
175#define UDI_HID_MOU_EP_SIZE MOUSE_EPSIZE
176#define MOU_POLLING_INTERVAL 10
177#ifndef UDI_HID_MOU_STRING_ID
178#define UDI_HID_MOU_STRING_ID 0
179#endif
180#else
181#define NEXT_IN_EPNUM_2 NEXT_IN_EPNUM_1
182#endif
183
184#ifdef EXK
185#define EXTRAKEY_IN_EPNUM NEXT_IN_EPNUM_2
186#define UDI_HID_EXK_EP_IN EXTRAKEY_IN_EPNUM
187#define NEXT_IN_EPNUM_3 (EXTRAKEY_IN_EPNUM + 1)
188#define UDI_HID_EXK_EP_SIZE EXTRAKEY_EPSIZE
189#define EXTRAKEY_POLLING_INTERVAL 10
190#ifndef UDI_HID_EXK_STRING_ID
191#define UDI_HID_EXK_STRING_ID 0
192#endif
193#else
194#define NEXT_IN_EPNUM_3 NEXT_IN_EPNUM_2
195#endif
196
197#ifdef RAW
198#define RAW_IN_EPNUM NEXT_IN_EPNUM_3
199#define UDI_HID_RAW_EP_IN RAW_IN_EPNUM
200#define NEXT_IN_EPNUM_4 (RAW_IN_EPNUM + 1)
201#define RAW_OUT_EPNUM NEXT_OUT_EPNUM_0
202#define UDI_HID_RAW_EP_OUT RAW_OUT_EPNUM
203#define NEXT_OUT_EPNUM_1 (RAW_OUT_EPNUM + 1)
204#define RAW_POLLING_INTERVAL 1
205#ifndef UDI_HID_RAW_STRING_ID
206#define UDI_HID_RAW_STRING_ID 0
207#endif
208#else
209#define NEXT_IN_EPNUM_4 NEXT_IN_EPNUM_3
210#define NEXT_OUT_EPNUM_1 NEXT_OUT_EPNUM_0
211#endif
212
213#ifdef CON
214#define CONSOLE_IN_EPNUM NEXT_IN_EPNUM_4
215#define NEXT_IN_EPNUM_5 (CONSOLE_IN_EPNUM + 1)
216#define CONSOLE_OUT_EPNUM NEXT_OUT_EPNUM_1
217#define NEXT_OUT_EPNUM_2 (CONSOLE_OUT_EPNUM + 1)
218#define CONSOLE_POLLING_INTERVAL 1
219#else
220#define NEXT_IN_EPNUM_5 NEXT_IN_EPNUM_4
221#define NEXT_OUT_EPNUM_2 NEXT_OUT_EPNUM_1
222#endif
223
224#ifdef NKRO
225#define NKRO_IN_EPNUM NEXT_IN_EPNUM_5
226#define UDI_HID_NKRO_EP_IN NKRO_IN_EPNUM
227#define NEXT_IN_EPNUM_6 (NKRO_IN_EPNUM + 1)
228#define UDI_HID_NKRO_EP_SIZE NKRO_EPSIZE
229#define NKRO_POLLING_INTERVAL 1
230#ifndef UDI_HID_NKRO_STRING_ID
231#define UDI_HID_NKRO_STRING_ID 0
232#endif
233#else
234#define NEXT_IN_EPNUM_6 NEXT_IN_EPNUM_5
235#endif
236
237#ifdef MIDI
238#define MIDI_STREAM_IN_EPNUM NEXT_IN_EPNUM_6
239#define NEXT_IN_EPNUM_7 (MIDI_STREAM_IN_EPNUM + 1)
240#define MIDI_STREAM_OUT_EPNUM NEXT_OUT_EPNUM_2
241#define NEXT_OUT_EPNUM_3 (MIDI_STREAM_OUT_EPNUM + 1)
242#define MIDI_POLLING_INTERVAL 5
243#else
244#define NEXT_IN_EPNUM_7 NEXT_IN_EPNUM_6
245#define NEXT_OUT_EPNUM_3 NEXT_OUT_EPNUM_2
246#endif
247
248#ifdef CDC
249#define CDC_NOTIFICATION_EPNUM NEXT_IN_EPNUM_7
250#define CDC_ACM_ENDPOINT CDC_NOTIFICATION_EPNUM
251#define CDC_TX_ENDPOINT (CDC_NOTIFICATION_EPNUM + 1)
252#define NEXT_IN_EPNUM_8 (CDC_TX_ENDPOINT + 1)
253
254#define CDC_OUT_EPNUM NEXT_OUT_EPNUM_3
255#define CDC_RX_ENDPOINT CDC_OUT_EPNUM
256#define NEXT_OUT_EPNUM_4 (CDC_OUT_EPNUM + 1)
257
258#define CDC_ACM_SIZE CDC_NOTIFICATION_EPSIZE
259#define CDC_RX_SIZE CDC_EPSIZE //KFSMOD was 64
260#define CDC_TX_SIZE CDC_RX_SIZE
261#define CDC_ACM_POLLING_INTERVAL 255
262#define CDC_EP_INTERVAL_STATUS CDC_ACM_POLLING_INTERVAL
263#define CDC_DATA_POLLING_INTERVAL 5
264#define CDC_EP_INTERVAL_DATA CDC_DATA_POLLING_INTERVAL
265#define CDC_STATUS_NAME L"Virtual Serial Port - Status"
266#define CDC_DATA_NAME L"Virtual Serial Port - Data"
267#else
268#define NEXT_IN_EPNUM_8 NEXT_IN_EPNUM_7
269#define NEXT_OUT_EPNUM_4 NEXT_OUT_EPNUM_3
270#endif
271
272#define TOTAL_OUT_EP NEXT_OUT_EPNUM_4
273#define TOTAL_IN_EP NEXT_IN_EPNUM_8
274#define USB_DEVICE_MAX_EP (max(NEXT_OUT_EPNUM_4, NEXT_IN_EPNUM_8))
275
276#if USB_DEVICE_MAX_EP > 8
277#error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, VIRTSER)"
278#endif
279
280
281// **********************************************************************
282// KBD Descriptor structure and content
283// **********************************************************************
284#ifdef KBD
285
286COMPILER_PACK_SET(1)
287
288typedef struct {
289 usb_iface_desc_t iface;
290 usb_hid_descriptor_t hid;
291 usb_ep_desc_t ep;
292} udi_hid_kbd_desc_t;
293
294typedef struct {
295 uint8_t array[59];
296} udi_hid_kbd_report_desc_t;
297
298#define UDI_HID_KBD_DESC {\
299 .iface.bLength = sizeof(usb_iface_desc_t),\
300 .iface.bDescriptorType = USB_DT_INTERFACE,\
301 .iface.bInterfaceNumber = UDI_HID_KBD_IFACE_NUMBER,\
302 .iface.bAlternateSetting = 0,\
303 .iface.bNumEndpoints = 1,\
304 .iface.bInterfaceClass = HID_CLASS,\
305 .iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
306 .iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
307 .iface.iInterface = UDI_HID_KBD_STRING_ID,\
308 .hid.bLength = sizeof(usb_hid_descriptor_t),\
309 .hid.bDescriptorType = USB_DT_HID,\
310 .hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
311 .hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
312 .hid.bNumDescriptors = USB_HID_NUM_DESC,\
313 .hid.bRDescriptorType = USB_DT_HID_REPORT,\
314 .hid.wDescriptorLength = LE16(sizeof(udi_hid_kbd_report_desc_t)),\
315 .ep.bLength = sizeof(usb_ep_desc_t),\
316 .ep.bDescriptorType = USB_DT_ENDPOINT,\
317 .ep.bEndpointAddress = UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,\
318 .ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
319 .ep.wMaxPacketSize = LE16(UDI_HID_KBD_EP_SIZE),\
320 .ep.bInterval = KBD_POLLING_INTERVAL,\
321}
322
323//set report buffer (from host)
324extern uint8_t udi_hid_kbd_report_set;
325
326//report buffer (to host)
327#define UDI_HID_KBD_REPORT_SIZE 8
328extern uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
329
330COMPILER_PACK_RESET()
331
332#endif //KBD
333
334// **********************************************************************
335// EXK Descriptor structure and content
336// **********************************************************************
337#ifdef EXK
338
339COMPILER_PACK_SET(1)
340
341typedef struct {
342 usb_iface_desc_t iface;
343 usb_hid_descriptor_t hid;
344 usb_ep_desc_t ep;
345} udi_hid_exk_desc_t;
346
347typedef struct {
348 uint8_t array[54];
349} udi_hid_exk_report_desc_t;
350
351#define UDI_HID_EXK_DESC {\
352 .iface.bLength = sizeof(usb_iface_desc_t),\
353 .iface.bDescriptorType = USB_DT_INTERFACE,\
354 .iface.bInterfaceNumber = UDI_HID_EXK_IFACE_NUMBER,\
355 .iface.bAlternateSetting = 0,\
356 .iface.bNumEndpoints = 1,\
357 .iface.bInterfaceClass = HID_CLASS,\
358 .iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
359 .iface.bInterfaceProtocol = HID_PROTOCOL_GENERIC,\
360 .iface.iInterface = UDI_HID_EXK_STRING_ID,\
361 .hid.bLength = sizeof(usb_hid_descriptor_t),\
362 .hid.bDescriptorType = USB_DT_HID,\
363 .hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
364 .hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
365 .hid.bNumDescriptors = USB_HID_NUM_DESC,\
366 .hid.bRDescriptorType = USB_DT_HID_REPORT,\
367 .hid.wDescriptorLength = LE16(sizeof(udi_hid_exk_report_desc_t)),\
368 .ep.bLength = sizeof(usb_ep_desc_t),\
369 .ep.bDescriptorType = USB_DT_ENDPOINT,\
370 .ep.bEndpointAddress = UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,\
371 .ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
372 .ep.wMaxPacketSize = LE16(UDI_HID_EXK_EP_SIZE),\
373 .ep.bInterval = EXTRAKEY_POLLING_INTERVAL,\
374}
375
376//set report buffer (from host)
377extern uint8_t udi_hid_exk_report_set;
378
379//report buffer
380#define UDI_HID_EXK_REPORT_SIZE 3
381
382typedef union {
383 struct {
384 uint8_t report_id;
385 uint16_t report_data;
386 } desc;
387 uint8_t raw[UDI_HID_EXK_REPORT_SIZE];
388} udi_hid_exk_report_t;
389
390extern udi_hid_exk_report_t udi_hid_exk_report;
391
392COMPILER_PACK_RESET()
393
394#endif //EXK
395
396// **********************************************************************
397// NKRO Descriptor structure and content
398// **********************************************************************
399#ifdef NKRO
400
401COMPILER_PACK_SET(1)
402
403typedef struct {
404 usb_iface_desc_t iface;
405 usb_hid_descriptor_t hid;
406 usb_ep_desc_t ep;
407} udi_hid_nkro_desc_t;
408
409typedef struct {
410 uint8_t array[57];
411} udi_hid_nkro_report_desc_t;
412
413#define UDI_HID_NKRO_DESC {\
414 .iface.bLength = sizeof(usb_iface_desc_t),\
415 .iface.bDescriptorType = USB_DT_INTERFACE,\
416 .iface.bInterfaceNumber = UDI_HID_NKRO_IFACE_NUMBER,\
417 .iface.bAlternateSetting = 0,\
418 .iface.bNumEndpoints = 1,\
419 .iface.bInterfaceClass = HID_CLASS,\
420 .iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
421 .iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
422 .iface.iInterface = UDI_HID_NKRO_STRING_ID,\
423 .hid.bLength = sizeof(usb_hid_descriptor_t),\
424 .hid.bDescriptorType = USB_DT_HID,\
425 .hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
426 .hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
427 .hid.bNumDescriptors = USB_HID_NUM_DESC,\
428 .hid.bRDescriptorType = USB_DT_HID_REPORT,\
429 .hid.wDescriptorLength = LE16(sizeof(udi_hid_nkro_report_desc_t)),\
430 .ep.bLength = sizeof(usb_ep_desc_t),\
431 .ep.bDescriptorType = USB_DT_ENDPOINT,\
432 .ep.bEndpointAddress = UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,\
433 .ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
434 .ep.wMaxPacketSize = LE16(UDI_HID_NKRO_EP_SIZE),\
435 .ep.bInterval = NKRO_POLLING_INTERVAL,\
436}
437
438//set report buffer
439extern uint8_t udi_hid_nkro_report_set;
440
441//report buffer
442#define UDI_HID_NKRO_REPORT_SIZE 32
443extern uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
444
445COMPILER_PACK_RESET()
446
447#endif //NKRO
448
449// **********************************************************************
450// MOU Descriptor structure and content
451// **********************************************************************
452#ifdef MOU
453
454COMPILER_PACK_SET(1)
455
456typedef struct {
457 usb_iface_desc_t iface;
458 usb_hid_descriptor_t hid;
459 usb_ep_desc_t ep;
460} udi_hid_mou_desc_t;
461
462typedef struct {
463 uint8_t array[77];//MOU PDS
464} udi_hid_mou_report_desc_t;
465
466#define UDI_HID_MOU_DESC {\
467 .iface.bLength = sizeof(usb_iface_desc_t),\
468 .iface.bDescriptorType = USB_DT_INTERFACE,\
469 .iface.bInterfaceNumber = MOUSE_INTERFACE,\
470 .iface.bAlternateSetting = 0,\
471 .iface.bNumEndpoints = 1,\
472 .iface.bInterfaceClass = HID_CLASS,\
473 .iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
474 .iface.bInterfaceProtocol = HID_PROTOCOL_MOUSE,\
475 .iface.iInterface = UDI_HID_MOU_STRING_ID,\
476 .hid.bLength = sizeof(usb_hid_descriptor_t),\
477 .hid.bDescriptorType = USB_DT_HID,\
478 .hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
479 .hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
480 .hid.bNumDescriptors = USB_HID_NUM_DESC,\
481 .hid.bRDescriptorType = USB_DT_HID_REPORT,\
482 .hid.wDescriptorLength = LE16(sizeof(udi_hid_mou_report_desc_t)),\
483 .ep.bLength = sizeof(usb_ep_desc_t),\
484 .ep.bDescriptorType = USB_DT_ENDPOINT,\
485 .ep.bEndpointAddress = UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,\
486 .ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
487 .ep.wMaxPacketSize = LE16(UDI_HID_MOU_EP_SIZE),\
488 .ep.bInterval = MOU_POLLING_INTERVAL,\
489}
490
491//no set report buffer
492
493//report buffer
494#define UDI_HID_MOU_REPORT_SIZE 5 //MOU PDS
495extern uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
496
497COMPILER_PACK_RESET()
498
499#endif //MOU
500
501// **********************************************************************
502// RAW Descriptor structure and content
503// **********************************************************************
504#ifdef RAW
505
506COMPILER_PACK_SET(1)
507
508typedef struct {
509 usb_iface_desc_t iface;
510 usb_hid_descriptor_t hid;
511 usb_ep_desc_t ep_out;
512 usb_ep_desc_t ep_in;
513} udi_hid_raw_desc_t;
514
515typedef struct {
516 uint8_t array[27];
517} udi_hid_raw_report_desc_t;
518
519#define UDI_HID_RAW_DESC {\
520 .iface.bLength = sizeof(usb_iface_desc_t),\
521 .iface.bDescriptorType = USB_DT_INTERFACE,\
522 .iface.bInterfaceNumber = RAW_INTERFACE,\
523 .iface.bAlternateSetting = 0,\
524 .iface.bNumEndpoints = 2,\
525 .iface.bInterfaceClass = HID_CLASS,\
526 .iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
527 .iface.bInterfaceProtocol = HID_SUB_CLASS_NOBOOT,\
528 .iface.iInterface = UDI_HID_RAW_STRING_ID,\
529 .hid.bLength = sizeof(usb_hid_descriptor_t),\
530 .hid.bDescriptorType = USB_DT_HID,\
531 .hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
532 .hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
533 .hid.bNumDescriptors = USB_HID_NUM_DESC,\
534 .hid.bRDescriptorType = USB_DT_HID_REPORT,\
535 .hid.wDescriptorLength = LE16(sizeof(udi_hid_raw_report_desc_t)),\
536 .ep_out.bLength = sizeof(usb_ep_desc_t),\
537 .ep_out.bDescriptorType = USB_DT_ENDPOINT,\
538 .ep_out.bEndpointAddress = UDI_HID_RAW_EP_OUT | USB_EP_DIR_OUT,\
539 .ep_out.bmAttributes = USB_EP_TYPE_INTERRUPT,\
540 .ep_out.wMaxPacketSize = LE16(RAW_EPSIZE),\
541 .ep_out.bInterval = RAW_POLLING_INTERVAL,\
542 .ep_in.bLength = sizeof(usb_ep_desc_t),\
543 .ep_in.bDescriptorType = USB_DT_ENDPOINT,\
544 .ep_in.bEndpointAddress = UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,\
545 .ep_in.bmAttributes = USB_EP_TYPE_INTERRUPT,\
546 .ep_in.wMaxPacketSize = LE16(RAW_EPSIZE),\
547 .ep_in.bInterval = RAW_POLLING_INTERVAL,\
548}
549
550#define UDI_HID_RAW_REPORT_SIZE RAW_EPSIZE
551
552extern uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
553
554//report buffer
555extern uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
556
557COMPILER_PACK_RESET()
558
559#endif //RAW
560
561// **********************************************************************
562// CDC Descriptor structure and content
563// **********************************************************************
564#ifdef CDC
565
566COMPILER_PACK_SET(1)
567
568typedef struct {
569 uint8_t bFunctionLength;
570 uint8_t bDescriptorType;
571 uint8_t bDescriptorSubtype;
572 le16_t bcdCDC;
573} usb_cdc_hdr_desc_t;
574
575typedef struct {
576 uint8_t bFunctionLength;
577 uint8_t bDescriptorType;
578 uint8_t bDescriptorSubtype;
579 uint8_t bmCapabilities;
580 uint8_t bDataInterface;
581} usb_cdc_call_mgmt_desc_t;
582
583typedef struct {
584 uint8_t bFunctionLength;
585 uint8_t bDescriptorType;
586 uint8_t bDescriptorSubtype;
587 uint8_t bmCapabilities;
588} usb_cdc_acm_desc_t;
589
590typedef struct {
591 uint8_t bFunctionLength;
592 uint8_t bDescriptorType;
593 uint8_t bDescriptorSubtype;
594 uint8_t bMasterInterface;
595 uint8_t bSlaveInterface0;
596} usb_cdc_union_desc_t;
597
598typedef struct {
599 usb_association_desc_t iaface;
600 usb_iface_desc_t iface_c;
601 usb_cdc_hdr_desc_t fd;
602 usb_cdc_call_mgmt_desc_t mfd;
603 usb_cdc_acm_desc_t acmd;
604 usb_cdc_union_desc_t ufd;
605 usb_ep_desc_t ep_c;
606 usb_iface_desc_t iface_d;
607 usb_ep_desc_t ep_tx;
608 usb_ep_desc_t ep_rx;
609} udi_cdc_desc_t;
610
611#define CDC_DESCRIPTOR {\
612 .iaface.bLength = sizeof(usb_association_desc_t),\
613 .iaface.bDescriptorType = USB_DT_IAD,\
614 .iaface.bFirstInterface = CDC_STATUS_INTERFACE,\
615 .iaface.bInterfaceCount = 2,\
616 .iaface.bFunctionClass = CDC_CLASS_DEVICE,\
617 .iaface.bFunctionSubClass = CDC_SUBCLASS_ACM,\
618 .iaface.bFunctionProtocol = CDC_PROTOCOL_V25TER,\
619 .iaface.iFunction = 0,\
620 .iface_c.bLength = sizeof(usb_iface_desc_t),\
621 .iface_c.bDescriptorType = USB_DT_INTERFACE,\
622 .iface_c.bInterfaceNumber = CDC_STATUS_INTERFACE,\
623 .iface_c.bAlternateSetting = 0,\
624 .iface_c.bNumEndpoints = 1,\
625 .iface_c.bInterfaceClass = 0x02,\
626 .iface_c.bInterfaceSubClass = 0x02,\
627 .iface_c.bInterfaceProtocol = CDC_PROTOCOL_V25TER,\
628 .iface_c.iInterface = 0,\
629 .fd.bFunctionLength = sizeof(usb_cdc_hdr_desc_t),\
630 .fd.bDescriptorType = CDC_CS_INTERFACE,\
631 .fd.bDescriptorSubtype = CDC_SCS_HEADER,\
632 .fd.bcdCDC = 0x0110,\
633 .mfd.bFunctionLength = sizeof(usb_cdc_call_mgmt_desc_t),\
634 .mfd.bDescriptorType = CDC_CS_INTERFACE,\
635 .mfd.bDescriptorSubtype = CDC_SCS_CALL_MGMT,\
636 .mfd.bmCapabilities = CDC_CALL_MGMT_SUPPORTED,\
637 .mfd.bDataInterface = CDC_DATA_INTERFACE,\
638 .acmd.bFunctionLength = sizeof(usb_cdc_acm_desc_t),\
639 .acmd.bDescriptorType = CDC_CS_INTERFACE,\
640 .acmd.bDescriptorSubtype = CDC_SCS_ACM,\
641 .acmd.bmCapabilities = CDC_ACM_SUPPORT_LINE_REQUESTS,\
642 .ufd.bFunctionLength = sizeof(usb_cdc_union_desc_t),\
643 .ufd.bDescriptorType = CDC_CS_INTERFACE,\
644 .ufd.bDescriptorSubtype = CDC_SCS_UNION,\
645 .ufd.bMasterInterface = CDC_STATUS_INTERFACE,\
646 .ufd.bSlaveInterface0 = CDC_DATA_INTERFACE,\
647 .ep_c.bLength = sizeof(usb_ep_desc_t),\
648 .ep_c.bDescriptorType = USB_DT_ENDPOINT,\
649 .ep_c.bEndpointAddress = CDC_ACM_ENDPOINT | USB_EP_DIR_IN,\
650 .ep_c.bmAttributes = USB_EP_TYPE_INTERRUPT,\
651 .ep_c.wMaxPacketSize = LE16(CDC_ACM_SIZE),\
652 .ep_c.bInterval = CDC_EP_INTERVAL_STATUS,\
653 .iface_d.bLength = sizeof(usb_iface_desc_t),\
654 .iface_d.bDescriptorType = USB_DT_INTERFACE,\
655 .iface_d.bInterfaceNumber = CDC_DATA_INTERFACE,\
656 .iface_d.bAlternateSetting = 0,\
657 .iface_d.bNumEndpoints = 2,\
658 .iface_d.bInterfaceClass = CDC_CLASS_DATA,\
659 .iface_d.bInterfaceSubClass = 0,\
660 .iface_d.bInterfaceProtocol = 0,\
661 .iface_d.iInterface = 0,\
662 .ep_rx.bLength = sizeof(usb_ep_desc_t),\
663 .ep_rx.bDescriptorType = USB_DT_ENDPOINT,\
664 .ep_rx.bEndpointAddress = CDC_RX_ENDPOINT | USB_EP_DIR_OUT,\
665 .ep_rx.bmAttributes = USB_EP_TYPE_BULK,\
666 .ep_rx.wMaxPacketSize = LE16(CDC_RX_SIZE),\
667 .ep_rx.bInterval = CDC_EP_INTERVAL_DATA,\
668 .ep_tx.bLength = sizeof(usb_ep_desc_t),\
669 .ep_tx.bDescriptorType = USB_DT_ENDPOINT,\
670 .ep_tx.bEndpointAddress = CDC_TX_ENDPOINT | USB_EP_DIR_IN,\
671 .ep_tx.bmAttributes = USB_EP_TYPE_BULK,\
672 .ep_tx.wMaxPacketSize = LE16(CDC_TX_SIZE),\
673 .ep_tx.bInterval = CDC_EP_INTERVAL_DATA,\
674}
675
676COMPILER_PACK_RESET()
677
678#endif //CDC
679
680// **********************************************************************
681// CONFIGURATION Descriptor structure and content
682// **********************************************************************
683COMPILER_PACK_SET(1)
684
685typedef struct {
686 usb_conf_desc_t conf;
687#ifdef KBD
688 udi_hid_kbd_desc_t hid_kbd;
689#endif
690#ifdef MOU
691 udi_hid_mou_desc_t hid_mou;
692#endif
693#ifdef EXK
694 udi_hid_exk_desc_t hid_exk;
695#endif
696#ifdef RAW
697 udi_hid_raw_desc_t hid_raw;
698#endif
699#ifdef CON
700 udi_hid_con_desc_t hid_con;
701#endif
702#ifdef NKRO
703 udi_hid_nkro_desc_t hid_nkro;
704#endif
705#ifdef MIDI
706 udi_hid_midi_desc_t hid_midi;
707#endif
708#ifdef CDC
709 udi_cdc_desc_t cdc_serial;
710#endif
711} udc_desc_t;
712
713COMPILER_PACK_RESET()
714
715#endif //_UDI_DEVICE_CONF_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
new file mode 100644
index 000000000..96d03c286
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
@@ -0,0 +1,32 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _UDI_DEVICE_EPSIZE_H_
19#define _UDI_DEVICE_EPSIZE_H_
20
21#define KEYBOARD_EPSIZE 8
22#define MOUSE_EPSIZE 8
23#define EXTRAKEY_EPSIZE 8
24#define RAW_EPSIZE 64
25#define CONSOLE_EPSIZE 32
26#define NKRO_EPSIZE 32
27#define MIDI_STREAM_EPSIZE 64
28#define CDC_NOTIFICATION_EPSIZE 8
29#define CDC_EPSIZE 16
30
31#endif //_UDI_DEVICE_EPSIZE_H_
32
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid.c b/tmk_core/protocol/arm_atsam/usb/udi_hid.c
new file mode 100644
index 000000000..131b7a0ec
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid.c
@@ -0,0 +1,162 @@
1/**
2 * \file
3 *
4 * \brief USB Device Human Interface Device (HID) interface.
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#include "conf_usb.h"
48#include "usb_protocol.h"
49#include "udd.h"
50#include "udc.h"
51#include "udi_hid.h"
52
53
54/**
55 * \ingroup udi_hid_group
56 * \defgroup udi_hid_group_internal Implementation of HID common library
57 * @{
58 */
59
60/**
61 * \brief Send the specific descriptors requested by SETUP request
62 *
63 * \retval true if the descriptor is supported
64 */
65static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc);
66
67bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) )
68{
69 if (Udd_setup_is_in()) {
70 // Requests Interface GET
71 if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) {
72 // Requests Standard Interface Get
73 switch (udd_g_ctrlreq.req.bRequest) {
74
75 case USB_REQ_GET_DESCRIPTOR:
76 return udi_hid_reqstdifaceget_descriptor(report_desc);
77 }
78 }
79 if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
80 // Requests Class Interface Get
81 switch (udd_g_ctrlreq.req.bRequest) {
82
83 case USB_REQ_HID_GET_REPORT:
84 return setup_report();
85
86 case USB_REQ_HID_GET_IDLE:
87 udd_g_ctrlreq.payload = rate;
88 udd_g_ctrlreq.payload_size = 1;
89 return true;
90
91 case USB_REQ_HID_GET_PROTOCOL:
92 udd_g_ctrlreq.payload = protocol;
93 udd_g_ctrlreq.payload_size = 1;
94 return true;
95 }
96 }
97 }
98 if (Udd_setup_is_out()) {
99 // Requests Interface SET
100 if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
101 // Requests Class Interface Set
102 switch (udd_g_ctrlreq.req.bRequest) {
103
104 case USB_REQ_HID_SET_REPORT:
105 return setup_report();
106
107 case USB_REQ_HID_SET_IDLE:
108 *rate = udd_g_ctrlreq.req.wValue >> 8;
109 return true;
110
111 case USB_REQ_HID_SET_PROTOCOL:
112 if (0 != udd_g_ctrlreq.req.wLength)
113 return false;
114 *protocol = udd_g_ctrlreq.req.wValue;
115 return true;
116 }
117 }
118 }
119 return false; // Request not supported
120}
121
122//---------------------------------------------
123//------- Internal routines
124
125static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc)
126{
127 usb_hid_descriptor_t UDC_DESC_STORAGE *ptr_hid_desc;
128
129 // Get the USB descriptor which is located after the interface descriptor
130 // This descriptor must be the HID descriptor
131 ptr_hid_desc = (usb_hid_descriptor_t UDC_DESC_STORAGE *) ((uint8_t *)
132 udc_get_interface_desc() + sizeof(usb_iface_desc_t));
133 if (USB_DT_HID != ptr_hid_desc->bDescriptorType)
134 return false;
135
136 // The SETUP request can ask for:
137 // - an USB_DT_HID descriptor
138 // - or USB_DT_HID_REPORT descriptor
139 // - or USB_DT_HID_PHYSICAL descriptor
140 if (USB_DT_HID == (uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
141 // USB_DT_HID descriptor requested then send it
142 udd_g_ctrlreq.payload = (uint8_t *) ptr_hid_desc;
143 udd_g_ctrlreq.payload_size =
144 min(udd_g_ctrlreq.req.wLength,
145 ptr_hid_desc->bLength);
146 return true;
147 }
148 // The HID_X descriptor requested must correspond to report type
149 // included in the HID descriptor
150 if (ptr_hid_desc->bRDescriptorType ==
151 (uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
152 // Send HID Report descriptor given by high level
153 udd_g_ctrlreq.payload = report_desc;
154 udd_g_ctrlreq.payload_size =
155 min(udd_g_ctrlreq.req.wLength,
156 le16_to_cpu(ptr_hid_desc->wDescriptorLength));
157 return true;
158 }
159 return false;
160}
161
162//@}
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid.h b/tmk_core/protocol/arm_atsam/usb/udi_hid.h
new file mode 100644
index 000000000..0edb09c1c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid.h
@@ -0,0 +1,85 @@
1/**
2 * \file
3 *
4 * \brief USB Device Human Interface Device (HID) interface definitions.
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDI_HID_H_
48#define _UDI_HID_H_
49
50#include "conf_usb.h"
51#include "usb_protocol.h"
52#include "usb_protocol_hid.h"
53#include "udd.h"
54
55#ifdef __cplusplus
56extern "C" {
57#endif
58
59/**
60 * \ingroup udi_group
61 * \defgroup udi_hid_group USB Device Interface (UDI) for Human Interface Device (HID)
62 *
63 * Common library for all Human Interface Device (HID) implementation.
64 *
65 * @{
66 */
67
68/**
69 * \brief Decode HID setup request
70 *
71 * \param rate Pointer on rate of current HID interface
72 * \param protocol Pointer on protocol of current HID interface
73 * \param report_desc Pointer on report descriptor of current HID interface
74 * \param set_report Pointer on set_report callback of current HID interface
75 *
76 * \return \c 1 if function was successfully done, otherwise \c 0.
77 */
78bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) );
79
80//@}
81
82#ifdef __cplusplus
83}
84#endif
85#endif // _UDI_HID_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
new file mode 100644
index 000000000..18f69350c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
@@ -0,0 +1,845 @@
1/**
2 * \file
3 *
4 * \brief USB Device Human Interface Device (HID) keyboard interface.
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#include "samd51j18a.h"
48#include "conf_usb.h"
49#include "usb_protocol.h"
50#include "udd.h"
51#include "udc.h"
52#include "udi_device_conf.h"
53#include "udi_hid.h"
54#include "udi_hid_kbd.h"
55#include <string.h>
56
57//***************************************************************************
58// KBD
59//***************************************************************************
60#ifdef KBD
61
62bool udi_hid_kbd_enable(void);
63void udi_hid_kbd_disable(void);
64bool udi_hid_kbd_setup(void);
65uint8_t udi_hid_kbd_getsetting(void);
66
67UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd = {
68 .enable = (bool(*)(void))udi_hid_kbd_enable,
69 .disable = (void (*)(void))udi_hid_kbd_disable,
70 .setup = (bool(*)(void))udi_hid_kbd_setup,
71 .getsetting = (uint8_t(*)(void))udi_hid_kbd_getsetting,
72 .sof_notify = NULL,
73};
74
75COMPILER_WORD_ALIGNED
76static uint8_t udi_hid_kbd_rate;
77
78COMPILER_WORD_ALIGNED
79static uint8_t udi_hid_kbd_protocol;
80
81COMPILER_WORD_ALIGNED
82uint8_t udi_hid_kbd_report_set;
83
84bool udi_hid_kbd_b_report_valid;
85
86COMPILER_WORD_ALIGNED
87uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
88
89static bool udi_hid_kbd_b_report_trans_ongoing;
90
91COMPILER_WORD_ALIGNED
92static uint8_t udi_hid_kbd_report_trans[UDI_HID_KBD_REPORT_SIZE];
93
94COMPILER_WORD_ALIGNED
95UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {
96 {
97 0x05, 0x01, // Usage Page (Generic Desktop)
98 0x09, 0x06, // Usage (Keyboard)
99 0xA1, 0x01, // Collection (Application)
100 0x05, 0x07, // Usage Page (Keyboard)
101 0x19, 0xE0, // Usage Minimum (224)
102 0x29, 0xE7, // Usage Maximum (231)
103 0x15, 0x00, // Logical Minimum (0)
104 0x25, 0x01, // Logical Maximum (1)
105 0x75, 0x01, // Report Size (1)
106 0x95, 0x08, // Report Count (8)
107 0x81, 0x02, // Input (Data, Variable, Absolute)
108 0x81, 0x01, // Input (Constant)
109 0x19, 0x00, // Usage Minimum (0)
110 0x29, 0x65, // Usage Maximum (101)
111 0x15, 0x00, // Logical Minimum (0)
112 0x25, 0x65, // Logical Maximum (101)
113 0x75, 0x08, // Report Size (8)
114 0x95, 0x06, // Report Count (6)
115 0x81, 0x00, // Input (Data, Array)
116 0x05, 0x08, // Usage Page (LED)
117 0x19, 0x01, // Usage Minimum (1)
118 0x29, 0x05, // Usage Maximum (5)
119 0x15, 0x00, // Logical Minimum (0)
120 0x25, 0x01, // Logical Maximum (1)
121 0x75, 0x01, // Report Size (1)
122 0x95, 0x05, // Report Count (5)
123 0x91, 0x02, // Output (Data, Variable, Absolute)
124 0x95, 0x03, // Report Count (3)
125 0x91, 0x01, // Output (Constant)
126 0xC0 // End Collection
127 }
128};
129
130static bool udi_hid_kbd_setreport(void);
131
132static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
133
134static void udi_hid_kbd_setreport_valid(void);
135
136bool udi_hid_kbd_enable(void)
137{
138 // Initialize internal values
139 udi_hid_kbd_rate = 0;
140 udi_hid_kbd_protocol = 0;
141 udi_hid_kbd_b_report_trans_ongoing = false;
142 memset(udi_hid_kbd_report, 0, UDI_HID_KBD_REPORT_SIZE);
143 udi_hid_kbd_b_report_valid = false;
144 return UDI_HID_KBD_ENABLE_EXT();
145}
146
147void udi_hid_kbd_disable(void)
148{
149 UDI_HID_KBD_DISABLE_EXT();
150}
151
152bool udi_hid_kbd_setup(void)
153{
154 return udi_hid_setup(&udi_hid_kbd_rate,
155 &udi_hid_kbd_protocol,
156 (uint8_t *) &udi_hid_kbd_report_desc,
157 udi_hid_kbd_setreport);
158}
159
160uint8_t udi_hid_kbd_getsetting(void)
161{
162 return 0;
163}
164
165static bool udi_hid_kbd_setreport(void)
166{
167 if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
168 && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
169 && (1 == udd_g_ctrlreq.req.wLength)) {
170 // Report OUT type on report ID 0 from USB Host
171 udd_g_ctrlreq.payload = &udi_hid_kbd_report_set;
172 udd_g_ctrlreq.callback = udi_hid_kbd_setreport_valid;
173 udd_g_ctrlreq.payload_size = 1;
174 return true;
175 }
176 return false;
177}
178
179bool udi_hid_kbd_send_report(void)
180{
181 if (!main_b_kbd_enable) {
182 return false;
183 }
184
185 if (udi_hid_kbd_b_report_trans_ongoing) {
186 return false;
187 }
188
189 memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report,
190 UDI_HID_KBD_REPORT_SIZE);
191 udi_hid_kbd_b_report_valid = false;
192 udi_hid_kbd_b_report_trans_ongoing =
193 udd_ep_run(UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,
194 false,
195 udi_hid_kbd_report_trans,
196 UDI_HID_KBD_REPORT_SIZE,
197 udi_hid_kbd_report_sent);
198
199 return udi_hid_kbd_b_report_trans_ongoing;
200}
201
202static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
203{
204 UNUSED(status);
205 UNUSED(nb_sent);
206 UNUSED(ep);
207 udi_hid_kbd_b_report_trans_ongoing = false;
208 if (udi_hid_kbd_b_report_valid) {
209 udi_hid_kbd_send_report();
210 }
211}
212
213static void udi_hid_kbd_setreport_valid(void)
214{
215 //UDI_HID_KBD_CHANGE_LED(udi_hid_kbd_report_set);
216}
217
218#endif //KBD
219
220//********************************************************************************************
221// NKRO Keyboard
222//********************************************************************************************
223#ifdef NKRO
224
225bool udi_hid_nkro_enable(void);
226void udi_hid_nkro_disable(void);
227bool udi_hid_nkro_setup(void);
228uint8_t udi_hid_nkro_getsetting(void);
229
230UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro = {
231 .enable = (bool(*)(void))udi_hid_nkro_enable,
232 .disable = (void (*)(void))udi_hid_nkro_disable,
233 .setup = (bool(*)(void))udi_hid_nkro_setup,
234 .getsetting = (uint8_t(*)(void))udi_hid_nkro_getsetting,
235 .sof_notify = NULL,
236};
237
238COMPILER_WORD_ALIGNED
239static uint8_t udi_hid_nkro_rate;
240
241COMPILER_WORD_ALIGNED
242static uint8_t udi_hid_nkro_protocol;
243
244COMPILER_WORD_ALIGNED
245uint8_t udi_hid_nkro_report_set;
246
247bool udi_hid_nkro_b_report_valid;
248
249COMPILER_WORD_ALIGNED
250uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
251
252static bool udi_hid_nkro_b_report_trans_ongoing;
253
254COMPILER_WORD_ALIGNED
255static uint8_t udi_hid_nkro_report_trans[UDI_HID_NKRO_REPORT_SIZE];
256
257COMPILER_WORD_ALIGNED
258UDC_DESC_STORAGE udi_hid_nkro_report_desc_t udi_hid_nkro_report_desc = {
259 {
260 0x05, 0x01, // Usage Page (Generic Desktop),
261 0x09, 0x06, // Usage (Keyboard),
262 0xA1, 0x01, // Collection (Application) - Keyboard,
263
264 //Mods
265 0x75, 0x01, // Report Size (1),
266 0x95, 0x08, // Report Count (8),
267 0x15, 0x00, // Logical Minimum (0),
268 0x25, 0x01, // Logical Maximum (1),
269 0x05, 0x07, // Usage Page (Key Codes),
270 0x19, 0xE0, // Usage Minimum (224),
271 0x29, 0xE7, // Usage Maximum (231),
272 0x81, 0x02, // Input (Data, Variable, Absolute),
273
274 //LED Report
275 0x75, 0x01, // Report Size (1),
276 0x95, 0x05, // Report Count (5),
277 0x05, 0x08, // Usage Page (LEDs),
278 0x19, 0x01, // Usage Minimum (1),
279 0x29, 0x05, // Usage Maximum (5),
280 0x91, 0x02, // Output (Data, Variable, Absolute),
281
282 //LED Report Padding
283 0x75, 0x03, // Report Size (3),
284 0x95, 0x01, // Report Count (1),
285 0x91, 0x03, // Output (Constant),
286
287 //Main keys
288 0x75, 0x01, // Report Size (1),
289 0x95, 0xF8, // Report Count (248),
290 0x15, 0x00, // Logical Minimum (0),
291 0x25, 0x01, // Logical Maximum (1),
292 0x05, 0x07, // Usage Page (Key Codes),
293 0x19, 0x00, // Usage Minimum (0),
294 0x29, 0xF7, // Usage Maximum (247),
295 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),
296 0xc0, // End Collection - Keyboard
297 }
298};
299
300static bool udi_hid_nkro_setreport(void);
301static void udi_hid_nkro_setreport_valid(void);
302static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
303
304bool udi_hid_nkro_enable(void)
305{
306 // Initialize internal values
307 udi_hid_nkro_rate = 0;
308 udi_hid_nkro_protocol = 0;
309 udi_hid_nkro_b_report_trans_ongoing = false;
310 memset(udi_hid_nkro_report, 0, UDI_HID_NKRO_REPORT_SIZE);
311 udi_hid_nkro_b_report_valid = false;
312 return UDI_HID_NKRO_ENABLE_EXT();
313}
314
315void udi_hid_nkro_disable(void)
316{
317 UDI_HID_NKRO_DISABLE_EXT();
318}
319
320bool udi_hid_nkro_setup(void)
321{
322 return udi_hid_setup(&udi_hid_nkro_rate,
323 &udi_hid_nkro_protocol,
324 (uint8_t *) &udi_hid_nkro_report_desc,
325 udi_hid_nkro_setreport);
326}
327
328uint8_t udi_hid_nkro_getsetting(void)
329{
330 return 0;
331}
332
333//keyboard receives LED report here
334static bool udi_hid_nkro_setreport(void)
335{
336 if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
337 && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
338 && (1 == udd_g_ctrlreq.req.wLength)) {
339 // Report OUT type on report ID 0 from USB Host
340 udd_g_ctrlreq.payload = &udi_hid_nkro_report_set;
341 udd_g_ctrlreq.callback = udi_hid_nkro_setreport_valid; //must call routine to transform setreport to LED state
342 udd_g_ctrlreq.payload_size = 1;
343 return true;
344 }
345 return false;
346}
347
348bool udi_hid_nkro_send_report(void)
349{
350 if (!main_b_nkro_enable) {
351 return false;
352 }
353
354 if (udi_hid_nkro_b_report_trans_ongoing) {
355 return false;
356 }
357
358 memcpy(udi_hid_nkro_report_trans, udi_hid_nkro_report,UDI_HID_NKRO_REPORT_SIZE);
359 udi_hid_nkro_b_report_valid = false;
360 udi_hid_nkro_b_report_trans_ongoing =
361 udd_ep_run(UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,
362 false,
363 udi_hid_nkro_report_trans,
364 UDI_HID_NKRO_REPORT_SIZE,
365 udi_hid_nkro_report_sent);
366
367 return udi_hid_nkro_b_report_trans_ongoing;
368}
369
370static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
371{
372 UNUSED(status);
373 UNUSED(nb_sent);
374 UNUSED(ep);
375 udi_hid_nkro_b_report_trans_ongoing = false;
376 if (udi_hid_nkro_b_report_valid) {
377 udi_hid_nkro_send_report();
378 }
379}
380
381static void udi_hid_nkro_setreport_valid(void)
382{
383 //UDI_HID_NKRO_CHANGE_LED(udi_hid_nkro_report_set);
384}
385
386#endif //NKRO
387
388//********************************************************************************************
389// EXK (extra-keys) SYS-CTRL Keyboard
390//********************************************************************************************
391#ifdef EXK
392
393bool udi_hid_exk_enable(void);
394void udi_hid_exk_disable(void);
395bool udi_hid_exk_setup(void);
396uint8_t udi_hid_exk_getsetting(void);
397
398UDC_DESC_STORAGE udi_api_t udi_api_hid_exk = {
399 .enable = (bool(*)(void))udi_hid_exk_enable,
400 .disable = (void (*)(void))udi_hid_exk_disable,
401 .setup = (bool(*)(void))udi_hid_exk_setup,
402 .getsetting = (uint8_t(*)(void))udi_hid_exk_getsetting,
403 .sof_notify = NULL,
404};
405
406COMPILER_WORD_ALIGNED
407static uint8_t udi_hid_exk_rate;
408
409COMPILER_WORD_ALIGNED
410static uint8_t udi_hid_exk_protocol;
411
412COMPILER_WORD_ALIGNED
413uint8_t udi_hid_exk_report_set;
414
415bool udi_hid_exk_b_report_valid;
416
417COMPILER_WORD_ALIGNED
418udi_hid_exk_report_t udi_hid_exk_report;
419
420static bool udi_hid_exk_b_report_trans_ongoing;
421
422COMPILER_WORD_ALIGNED
423static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE];
424
425COMPILER_WORD_ALIGNED
426UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
427 {
428 // System Control Collection (8 bits)
429
430 0x05, 0x01, // Usage Page (Generic Desktop),
431 0x09, 0x80, // Usage (System Control),
432 0xA1, 0x01, // Collection (Application),
433 0x85, 0x02, // Report ID (2) (System),
434 0x16, 0x01, 0x00, // Logical Minimum (1),
435 0x26, 0x03, 0x00, // Logical Maximum (3),
436 0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
437 0x2A, 0x83, 0x00, // Usage Maximum (83) (System Wake Up),
438 0x75, 0x10, // Report Size (16),
439 0x95, 0x01, // Report Count (1),
440 0x81, 0x00, // Input (Data, Array),
441 0xC0, // End Collection - System Control
442
443 // Consumer Control Collection - Media Keys (16 bits)
444
445 0x05, 0x0C, // Usage Page (Consumer),
446 0x09, 0x01, // Usage (Consumer Control),
447 0xA1, 0x01, // Collection (Application),
448 0x85, 0x03, // Report ID (3) (Consumer),
449 0x16, 0x01, 0x00, // Logical Minimum (1),
450 0x26, 0x9C, 0x02, // Logical Maximum (668),
451 0x1A, 0x01, 0x00, // Usage Minimum (1),
452 0x2A, 0x9C, 0x02, // Usage Maximum (668),
453 0x75, 0x10, // Report Size (16),
454 0x95, 0x01, // Report Count (1),
455 0x81, 0x00, // Input (Data, Array),
456 0xC0, // End Collection - Consumer Control
457 }
458};
459
460static bool udi_hid_exk_setreport(void);
461
462static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
463
464static void udi_hid_exk_setreport_valid(void);
465
466bool udi_hid_exk_enable(void)
467{
468 // Initialize internal values
469 udi_hid_exk_rate = 0;
470 udi_hid_exk_protocol = 0;
471 udi_hid_exk_b_report_trans_ongoing = false;
472 memset(udi_hid_exk_report.raw, 0, UDI_HID_EXK_REPORT_SIZE);
473 udi_hid_exk_b_report_valid = false;
474 return UDI_HID_EXK_ENABLE_EXT();
475}
476
477void udi_hid_exk_disable(void)
478{
479 UDI_HID_EXK_DISABLE_EXT();
480}
481
482bool udi_hid_exk_setup(void)
483{
484 return udi_hid_setup(&udi_hid_exk_rate,
485 &udi_hid_exk_protocol,
486 (uint8_t *) &udi_hid_exk_report_desc,
487 udi_hid_exk_setreport);
488}
489
490uint8_t udi_hid_exk_getsetting(void)
491{
492 return 0;
493}
494
495static bool udi_hid_exk_setreport(void)
496{
497 if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
498 && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
499 && (1 == udd_g_ctrlreq.req.wLength)) {
500 // Report OUT type on report ID 0 from USB Host
501 udd_g_ctrlreq.payload = &udi_hid_exk_report_set;
502 udd_g_ctrlreq.callback = udi_hid_exk_setreport_valid;
503 udd_g_ctrlreq.payload_size = 1;
504 return true;
505 }
506 return false;
507}
508
509bool udi_hid_exk_send_report(void)
510{
511 if (!main_b_exk_enable) {
512 return false;
513 }
514
515 if (udi_hid_exk_b_report_trans_ongoing) {
516 return false;
517 }
518
519 memcpy(udi_hid_exk_report_trans, udi_hid_exk_report.raw, UDI_HID_EXK_REPORT_SIZE);
520 udi_hid_exk_b_report_valid = false;
521 udi_hid_exk_b_report_trans_ongoing =
522 udd_ep_run(UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,
523 false,
524 udi_hid_exk_report_trans,
525 UDI_HID_EXK_REPORT_SIZE,
526 udi_hid_exk_report_sent);
527
528 return udi_hid_exk_b_report_trans_ongoing;
529}
530
531static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
532{
533 UNUSED(status);
534 UNUSED(nb_sent);
535 UNUSED(ep);
536 udi_hid_exk_b_report_trans_ongoing = false;
537 if (udi_hid_exk_b_report_valid) {
538 udi_hid_exk_send_report();
539 }
540}
541
542static void udi_hid_exk_setreport_valid(void)
543{
544
545}
546
547#endif //EXK
548
549//********************************************************************************************
550// MOU Mouse
551//********************************************************************************************
552#ifdef MOU
553
554bool udi_hid_mou_enable(void);
555void udi_hid_mou_disable(void);
556bool udi_hid_mou_setup(void);
557uint8_t udi_hid_mou_getsetting(void);
558
559UDC_DESC_STORAGE udi_api_t udi_api_hid_mou = {
560 .enable = (bool(*)(void))udi_hid_mou_enable,
561 .disable = (void (*)(void))udi_hid_mou_disable,
562 .setup = (bool(*)(void))udi_hid_mou_setup,
563 .getsetting = (uint8_t(*)(void))udi_hid_mou_getsetting,
564 .sof_notify = NULL,
565};
566
567COMPILER_WORD_ALIGNED
568static uint8_t udi_hid_mou_rate;
569
570COMPILER_WORD_ALIGNED
571static uint8_t udi_hid_mou_protocol;
572
573//COMPILER_WORD_ALIGNED
574//uint8_t udi_hid_mou_report_set; //No set report
575
576bool udi_hid_mou_b_report_valid;
577
578COMPILER_WORD_ALIGNED
579uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
580
581static bool udi_hid_mou_b_report_trans_ongoing;
582
583COMPILER_WORD_ALIGNED
584static uint8_t udi_hid_mou_report_trans[UDI_HID_MOU_REPORT_SIZE];
585
586COMPILER_WORD_ALIGNED
587UDC_DESC_STORAGE udi_hid_mou_report_desc_t udi_hid_mou_report_desc = {
588 {
589 0x05, 0x01, // Usage Page (Generic Desktop),
590 0x09, 0x02, // Usage (Mouse),
591 0xA1, 0x01, // Collection (Application),
592 0x09, 0x01, // Usage (Pointer),
593 0xA1, 0x00, // Collection (Physical),
594 0x05, 0x09, // Usage Page (Buttons),
595 0x19, 0x01, // Usage Minimum (01),
596 0x29, 0x05, // Usage Maximun (05),
597 0x15, 0x00, // Logical Minimum (0),
598 0x25, 0x01, // Logical Maximum (1),
599 0x95, 0x05, // Report Count (5),
600 0x75, 0x01, // Report Size (1),
601 0x81, 0x02, // Input (Data, Variable, Absolute), ;5 button bits
602 0x95, 0x01, // Report Count (1),
603 0x75, 0x03, // Report Size (3),
604 0x81, 0x01, // Input (Constant), ;3 bit padding,
605
606 0x05, 0x01, // Usage Page (Generic Desktop),
607 0x09, 0x30, // Usage (X),
608 0x09, 0x31, // Usage (Y),
609 0x15, 0x81, // Logical Minimum (-127),
610 0x25, 0x7F, // Logical Maximum (127),
611 0x95, 0x02, // Report Count (2),
612 0x75, 0x08, // Report Size (8),
613 0x81, 0x06, // Input (Data, Variable, Relative), ;2 position bytes (X & Y),
614
615 0x09, 0x38, // Usage (Wheel),
616 0x15, 0x81, // Logical Minimum (-127),
617 0x25, 0x7F, // Logical Maximum (127),
618 0x95, 0x01, // Report Count (1),
619 0x75, 0x08, // Report Size (8),
620 0x81, 0x06, // Input (Data, Variable, Relative),
621
622 0x05, 0x0C, // Usage Page (Consumer),
623 0x0A, 0x38, 0x02, // Usage (AC Pan (Horizontal wheel)),
624 0x15, 0x81, // Logical Minimum (-127),
625 0x25, 0x7F, // Logical Maximum (127),
626 0x95, 0x01, // Report Count (1),
627 0x75, 0x08, // Report Size (8),
628 0x81, 0x06, // Input (Data, Variable, Relative),
629
630 0xC0, // End Collection,
631 0xC0, // End Collection
632 }
633};
634
635static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
636
637bool udi_hid_mou_enable(void)
638{
639 // Initialize internal values
640 udi_hid_mou_rate = 0;
641 udi_hid_mou_protocol = 0;
642 udi_hid_mou_b_report_trans_ongoing = false;
643 memset(udi_hid_mou_report, 0, UDI_HID_MOU_REPORT_SIZE);
644 udi_hid_mou_b_report_valid = false;
645 return UDI_HID_MOU_ENABLE_EXT();
646}
647
648void udi_hid_mou_disable(void)
649{
650 UDI_HID_MOU_DISABLE_EXT();
651}
652
653bool udi_hid_mou_setup(void)
654{
655 return udi_hid_setup(&udi_hid_mou_rate,
656 &udi_hid_mou_protocol,
657 (uint8_t *) &udi_hid_mou_report_desc,
658 NULL);
659}
660
661uint8_t udi_hid_mou_getsetting(void)
662{
663 return 0;
664}
665
666bool udi_hid_mou_send_report(void)
667{
668 if (!main_b_mou_enable) {
669 return false;
670 }
671
672 if (udi_hid_mou_b_report_trans_ongoing) {
673 return false;
674 }
675
676 memcpy(udi_hid_mou_report_trans, udi_hid_mou_report, UDI_HID_MOU_REPORT_SIZE);
677 udi_hid_mou_b_report_valid = false;
678 udi_hid_mou_b_report_trans_ongoing =
679 udd_ep_run(UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,
680 false,
681 udi_hid_mou_report_trans,
682 UDI_HID_MOU_REPORT_SIZE,
683 udi_hid_mou_report_sent);
684
685 return udi_hid_mou_b_report_trans_ongoing;
686}
687
688static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
689{
690 UNUSED(status);
691 UNUSED(nb_sent);
692 UNUSED(ep);
693 udi_hid_mou_b_report_trans_ongoing = false;
694 if (udi_hid_mou_b_report_valid) {
695 udi_hid_mou_send_report();
696 }
697}
698
699#endif //MOU
700
701//********************************************************************************************
702// RAW
703//********************************************************************************************
704#ifdef RAW
705
706bool udi_hid_raw_enable(void);
707void udi_hid_raw_disable(void);
708bool udi_hid_raw_setup(void);
709uint8_t udi_hid_raw_getsetting(void);
710
711UDC_DESC_STORAGE udi_api_t udi_api_hid_raw = {
712 .enable = (bool(*)(void))udi_hid_raw_enable,
713 .disable = (void (*)(void))udi_hid_raw_disable,
714 .setup = (bool(*)(void))udi_hid_raw_setup,
715 .getsetting = (uint8_t(*)(void))udi_hid_raw_getsetting,
716 .sof_notify = NULL,
717};
718
719COMPILER_WORD_ALIGNED
720static uint8_t udi_hid_raw_rate;
721
722COMPILER_WORD_ALIGNED
723static uint8_t udi_hid_raw_protocol;
724
725COMPILER_WORD_ALIGNED
726uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
727
728static bool udi_hid_raw_b_report_valid;
729
730COMPILER_WORD_ALIGNED
731uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
732
733static bool udi_hid_raw_b_report_trans_ongoing;
734
735COMPILER_WORD_ALIGNED
736static uint8_t udi_hid_raw_report_trans[UDI_HID_RAW_REPORT_SIZE];
737
738COMPILER_WORD_ALIGNED
739UDC_DESC_STORAGE udi_hid_raw_report_desc_t udi_hid_raw_report_desc = {
740 {
741 0x06, // Usage Page (Vendor Defined)
742 0xFF, 0xFF,
743 0x0A, // Usage (Mouse)
744 0xFF, 0xFF,
745 0xA1, 0x01, // Collection (Application)
746 0x75, 0x08, // Report Size (8)
747 0x15, 0x00, // Logical Minimum (0)
748 0x25, 0xFF, // Logical Maximum (255)
749 0x95, 0x40, // Report Count
750 0x09, 0x01, // Usage (Input)
751 0x81, 0x02, // Input (Data
752 0x95, 0x40, // Report Count
753 0x09, 0x02, // Usage (Output)
754 0x91, 0x02, // Output (Data
755 0xC0, // End Collection - Consumer Control
756 }
757};
758
759static bool udi_hid_raw_setreport(void);
760static void udi_hid_raw_setreport_valid(void);
761
762static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
763
764bool udi_hid_raw_enable(void)
765{
766 // Initialize internal values
767 udi_hid_raw_rate = 0;
768 udi_hid_raw_protocol = 0;
769 udi_hid_raw_b_report_trans_ongoing = false;
770 memset(udi_hid_raw_report, 0, UDI_HID_RAW_REPORT_SIZE);
771 udi_hid_raw_b_report_valid = false;
772 return UDI_HID_RAW_ENABLE_EXT();
773}
774
775void udi_hid_raw_disable(void)
776{
777 UDI_HID_RAW_DISABLE_EXT();
778}
779
780bool udi_hid_raw_setup(void)
781{
782 return udi_hid_setup(&udi_hid_raw_rate,
783 &udi_hid_raw_protocol,
784 (uint8_t *) &udi_hid_raw_report_desc,
785 udi_hid_raw_setreport);
786}
787
788uint8_t udi_hid_raw_getsetting(void)
789{
790 return 0;
791}
792
793static bool udi_hid_raw_setreport(void)
794{
795 if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
796 && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
797 && (UDI_HID_RAW_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
798 // Report OUT type on report ID 0 from USB Host
799 udd_g_ctrlreq.payload = udi_hid_raw_report_set;
800 udd_g_ctrlreq.callback = udi_hid_raw_setreport_valid; //must call routine to transform setreport to LED state
801 udd_g_ctrlreq.payload_size = UDI_HID_RAW_REPORT_SIZE;
802 return true;
803 }
804 return false;
805}
806
807bool udi_hid_raw_send_report(void)
808{
809 if (!main_b_raw_enable) {
810 return false;
811 }
812
813 if (udi_hid_raw_b_report_trans_ongoing) {
814 return false;
815 }
816
817 memcpy(udi_hid_raw_report_trans, udi_hid_raw_report,UDI_HID_RAW_REPORT_SIZE);
818 udi_hid_raw_b_report_valid = false;
819 udi_hid_raw_b_report_trans_ongoing =
820 udd_ep_run(UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,
821 false,
822 udi_hid_raw_report_trans,
823 UDI_HID_RAW_REPORT_SIZE,
824 udi_hid_raw_report_sent);
825
826 return udi_hid_raw_b_report_trans_ongoing;
827}
828
829static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
830{
831 UNUSED(status);
832 UNUSED(nb_sent);
833 UNUSED(ep);
834 udi_hid_raw_b_report_trans_ongoing = false;
835 if (udi_hid_raw_b_report_valid) {
836 udi_hid_raw_send_report();
837 }
838}
839
840static void udi_hid_raw_setreport_valid(void)
841{
842
843}
844
845#endif //RAW
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h
new file mode 100644
index 000000000..9a2741534
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h
@@ -0,0 +1,109 @@
1/**
2 * \file
3 *
4 * \brief USB Device Human Interface Device (HID) keyboard interface.
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UDC_HID_KBD_H_
48#define _UDC_HID_KBD_H_
49
50#include "udc_desc.h"
51#include "udi.h"
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57//******************************************************************************
58// Keyboard interface definitions
59//******************************************************************************
60#ifdef KBD
61extern UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd;
62extern bool udi_hid_kbd_b_report_valid;
63extern uint8_t udi_hid_kbd_report_set;
64bool udi_hid_kbd_send_report(void);
65#endif //KBD
66
67//********************************************************************************************
68// NKRO Keyboard
69//********************************************************************************************
70#ifdef NKRO
71extern UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro;
72extern bool udi_hid_nkro_b_report_valid;
73bool udi_hid_nkro_send_report(void);
74#endif //NKRO
75
76//********************************************************************************************
77// SYS-CTRL interface
78//********************************************************************************************
79#ifdef EXK
80extern UDC_DESC_STORAGE udi_api_t udi_api_hid_exk;
81extern bool udi_hid_exk_b_report_valid;
82extern uint8_t udi_hid_exk_report_set;
83bool udi_hid_exk_send_report(void);
84#endif //EXK
85
86//********************************************************************************************
87// MOU Mouse
88//********************************************************************************************
89#ifdef MOU
90extern UDC_DESC_STORAGE udi_api_t udi_api_hid_mou;
91extern bool udi_hid_mou_b_report_valid;
92bool udi_hid_mou_send_report(void);
93#endif //MOU
94
95//********************************************************************************************
96// RAW Raw
97//********************************************************************************************
98#ifdef RAW
99extern UDC_DESC_STORAGE udi_api_t udi_api_hid_raw;
100bool udi_hid_raw_send_report(void);
101#endif //RAW
102
103//@}
104
105#ifdef __cplusplus
106}
107#endif
108
109#endif // _UDC_HID_KBD_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h
new file mode 100644
index 000000000..db5db17ed
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h
@@ -0,0 +1,60 @@
1/**
2 * \file
3 *
4 * \brief Default HID keyboard configuration for a USB Device
5 * with a single interface HID keyboard
6 *
7 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
8 *
9 * \asf_license_start
10 *
11 * \page License
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 *
23 * 3. The name of Atmel may not be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * 4. This software may only be redistributed and used in connection with an
27 * Atmel microcontroller product.
28 *
29 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
32 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
33 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 *
41 * \asf_license_stop
42 *
43 */
44/*
45 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
46 */
47
48#ifndef _UDI_HID_KBD_CONF_H_
49#define _UDI_HID_KBD_CONF_H_
50
51/**
52 * \addtogroup udi_hid_keyboard_group_single_desc
53 * @{
54 */
55
56#include "udi_device_conf.h"
57
58#include "udi_hid_kbd.h"
59
60#endif // _UDI_HID_KBD_CONF_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c
new file mode 100644
index 000000000..16bd4e514
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c
@@ -0,0 +1,179 @@
1/**
2 * \file
3 *
4 * \brief Default descriptors for a USB Device
5 * with a single interface HID keyboard
6 *
7 * Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
8 *
9 * \asf_license_start
10 *
11 * \page License
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 *
23 * 3. The name of Atmel may not be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * 4. This software may only be redistributed and used in connection with an
27 * Atmel microcontroller product.
28 *
29 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
32 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
33 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 *
41 * \asf_license_stop
42 *
43 */
44/*
45 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
46 */
47
48#include "conf_usb.h"
49#include "usb_protocol.h"
50#include "udc_desc.h"
51#include "udi_device_conf.h"
52#include "udi_hid_kbd.h"
53#include "udi_cdc.h"
54
55/**
56 * \ingroup udi_hid_keyboard_group
57 * \defgroup udi_hid_keyboard_group_single_desc USB device descriptors for a single interface
58 *
59 * The following structures provide the USB device descriptors required
60 * for USB Device with a single interface HID keyboard.
61 *
62 * It is ready to use and do not require more definition.
63 * @{
64 */
65
66//! USB Device Descriptor
67COMPILER_WORD_ALIGNED
68UDC_DESC_STORAGE usb_dev_desc_t udc_device_desc = {
69 .bLength = sizeof(usb_dev_desc_t),
70 .bDescriptorType = USB_DT_DEVICE,
71 .bcdUSB = LE16(USB_V2_0),
72 .bDeviceClass = DEVICE_CLASS,
73 .bDeviceSubClass = DEVICE_SUBCLASS,
74 .bDeviceProtocol = DEVICE_PROTOCOL,
75 .bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
76 .idVendor = LE16(USB_DEVICE_VENDOR_ID),
77 .idProduct = LE16(USB_DEVICE_PRODUCT_ID),
78 .bcdDevice = LE16(USB_DEVICE_VERSION),
79#ifdef USB_DEVICE_MANUFACTURE_NAME
80 .iManufacturer = 1,
81#else
82 .iManufacturer = 0, // No manufacture string
83#endif
84#ifdef USB_DEVICE_PRODUCT_NAME
85 .iProduct = 2,
86#else
87 .iProduct = 0, // No product string
88#endif
89#if (defined USB_DEVICE_SERIAL_NAME || defined USB_DEVICE_GET_SERIAL_NAME_POINTER)
90 .iSerialNumber = 3,
91#else
92 .iSerialNumber = 0, // No serial string
93#endif
94 .bNumConfigurations = 1
95};
96
97#if 0
98#ifdef USB_DEVICE_HS_SUPPORT
99//! USB Device Qualifier Descriptor for HS
100COMPILER_WORD_ALIGNED
101UDC_DESC_STORAGE usb_dev_qual_desc_t udc_device_qual = {
102 .bLength = sizeof(usb_dev_qual_desc_t),
103 .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
104 .bcdUSB = LE16(USB_V2_0),
105 .bDeviceClass = 0,
106 .bDeviceSubClass = 0,
107 .bDeviceProtocol = 0,
108 .bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
109 .bNumConfigurations = 1
110};
111#endif
112#endif
113
114//! USB Device Configuration Descriptor filled for FS and HS
115COMPILER_WORD_ALIGNED
116UDC_DESC_STORAGE udc_desc_t udc_desc = {
117 .conf.bLength = sizeof(usb_conf_desc_t),
118 .conf.bDescriptorType = USB_DT_CONFIGURATION,
119 .conf.wTotalLength = LE16(sizeof(udc_desc_t)),
120 .conf.bNumInterfaces = USB_DEVICE_NB_INTERFACE,
121 .conf.bConfigurationValue = 1,
122 .conf.iConfiguration = 0,
123 .conf.bmAttributes = /* USB_CONFIG_ATTR_MUST_SET | */ USB_DEVICE_ATTR,
124 .conf.bMaxPower = USB_CONFIG_MAX_POWER(USB_DEVICE_POWER),
125#ifdef KBD
126 .hid_kbd = UDI_HID_KBD_DESC,
127#endif
128#ifdef RAW
129 .hid_raw = UDI_HID_RAW_DESC,
130#endif
131#ifdef MOU
132 .hid_mou = UDI_HID_MOU_DESC,
133#endif
134#ifdef EXK
135 .hid_exk = UDI_HID_EXK_DESC,
136#endif
137#ifdef NKRO
138 .hid_nkro = UDI_HID_NKRO_DESC,
139#endif
140#ifdef CDC
141 .cdc_serial = CDC_DESCRIPTOR,
142#endif
143};
144
145UDC_DESC_STORAGE udi_api_t *udi_apis[USB_DEVICE_NB_INTERFACE] = {
146 #ifdef KBD
147 &udi_api_hid_kbd,
148 #endif
149 #ifdef RAW
150 &udi_api_hid_raw,
151 #endif
152 #ifdef MOU
153 &udi_api_hid_mou,
154 #endif
155 #ifdef EXK
156 &udi_api_hid_exk,
157 #endif
158 #ifdef NKRO
159 &udi_api_hid_nkro,
160 #endif
161 #ifdef CDC
162 &udi_api_cdc_comm, &udi_api_cdc_data,
163 #endif
164};
165
166//! Add UDI with USB Descriptors FS & HS
167UDC_DESC_STORAGE udc_config_speed_t udc_config_fshs[1] = {{
168 .desc = (usb_conf_desc_t UDC_DESC_STORAGE*)&udc_desc,
169 .udi_apis = udi_apis,
170}};
171
172//! Add all information about USB Device in global structure for UDC
173UDC_DESC_STORAGE udc_config_t udc_config = {
174 .confdev_lsfs = &udc_device_desc,
175 .conf_lsfs = udc_config_fshs,
176};
177
178//@}
179//@}
diff --git a/tmk_core/protocol/arm_atsam/usb/ui.c b/tmk_core/protocol/arm_atsam/usb/ui.c
new file mode 100644
index 000000000..031678b64
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/ui.c
@@ -0,0 +1,106 @@
1/**
2 * \file
3 *
4 * \brief User Interface
5 *
6 * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef ARM_MATH_CM4
48 #define ARM_MATH_CM4
49#endif
50
51#undef LITTLE_ENDIAN //redefined in samd51j18a.h
52#include "samd51j18a.h"
53#include "ui.h"
54
55volatile uint8_t usb_state;
56
57//! Sequence process running each \c SEQUENCE_PERIOD ms
58#define SEQUENCE_PERIOD 150
59
60#if 0
61/* Interrupt on "pin change" from push button to do wakeup on USB
62 * Note:
63 * This interrupt is enable when the USB host enable remote wakeup feature
64 * This interrupt wakeup the CPU if this one is in idle mode
65 */
66static void ui_wakeup_handler(void)
67{
68 /* It is a wakeup then send wakeup USB */
69 udc_remotewakeup();
70}
71#endif
72
73void ui_init(void)
74{
75 usb_state = USB_STATE_POWERUP;
76}
77
78void ui_powerdown(void)
79{
80 usb_state = USB_STATE_POWERDOWN;
81}
82
83void ui_wakeup_enable(void)
84{
85
86}
87
88void ui_wakeup_disable(void)
89{
90
91}
92
93void ui_wakeup(void)
94{
95 usb_state = USB_STATE_POWERUP;
96}
97
98void ui_process(uint16_t framenumber)
99{
100
101}
102
103void ui_kbd_led(uint8_t value)
104{
105
106}
diff --git a/tmk_core/protocol/arm_atsam/usb/ui.h b/tmk_core/protocol/arm_atsam/usb/ui.h
new file mode 100644
index 000000000..3d899e669
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/ui.h
@@ -0,0 +1,82 @@
1/**
2 * \file
3 *
4 * \brief Common User Interface for HID Keyboard application
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _UI_H_
48#define _UI_H_
49
50extern volatile uint8_t usb_state;
51
52#define USB_STATE_UNKNOWN 0
53#define USB_STATE_POWERDOWN 1
54#define USB_STATE_POWERUP 2
55
56//! \brief Initializes the user interface
57void ui_init(void);
58
59//! \brief Enters the user interface in power down mode
60void ui_powerdown(void);
61
62//! \brief Enables the asynchronous interrupts of the user interface
63void ui_wakeup_enable(void);
64
65//! \brief Disables the asynchronous interrupts of the user interface
66void ui_wakeup_disable(void);
67
68//! \brief Exits the user interface of power down mode
69void ui_wakeup(void);
70
71/*! \brief This process is called each 1ms
72 * It is called only if the USB interface is enabled.
73 *
74 * \param framenumber Current frame number
75 */
76void ui_process(uint16_t framenumber);
77
78/*! \brief Turn on or off the keyboard LEDs
79 */
80void ui_kbd_led(uint8_t value);
81
82#endif // _UI_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/usb.c b/tmk_core/protocol/arm_atsam/usb/usb.c
new file mode 100644
index 000000000..d30d76dd1
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb.c
@@ -0,0 +1,1144 @@
1/**
2 * \file
3 *
4 * \brief SAM USB Driver.
5 *
6 * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#define DEVICE_MODE_ONLY true
48#define SAMD11 DEVICE_MODE_ONLY
49
50#ifndef ARM_MATH_CM4
51 #define ARM_MATH_CM4
52#endif
53
54#include "compiler.h"
55#undef LITTLE_ENDIAN //redefined in samd51j18a.h
56#include "samd51j18a.h"
57#include <stdbool.h>
58#include <string.h>
59#include "arm_math.h"
60#include "status_codes.h"
61#include "usb.h"
62
63/** Fields definition from a LPM TOKEN */
64#define USB_LPM_ATTRIBUT_BLINKSTATE_MASK (0xF << 0)
65#define USB_LPM_ATTRIBUT_HIRD_MASK (0xF << 4)
66#define USB_LPM_ATTRIBUT_REMOTEWAKE_MASK (1 << 8)
67#define USB_LPM_ATTRIBUT_BLINKSTATE(value) ((value & 0xF) << 0)
68#define USB_LPM_ATTRIBUT_HIRD(value) ((value & 0xF) << 4)
69#define USB_LPM_ATTRIBUT_REMOTEWAKE(value) ((value & 1) << 8)
70#define USB_LPM_ATTRIBUT_BLINKSTATE_L1 USB_LPM_ATTRIBUT_BLINKSTATE(1)
71
72/**
73 * \brief Mask selecting the index part of an endpoint address
74 */
75#define USB_EP_ADDR_MASK 0x0f
76
77/**
78 * \brief Endpoint transfer direction is IN
79 */
80#define USB_EP_DIR_IN 0x80
81
82/**
83 * \brief Endpoint transfer direction is OUT
84 */
85#define USB_EP_DIR_OUT 0x00
86
87/**
88 * \name USB SRAM data containing pipe descriptor table
89 * The content of the USB SRAM can be :
90 * - modified by USB hardware interface to update pipe status.
91 * Thereby, it is read by software.
92 * - modified by USB software to control pipe.
93 * Thereby, it is read by hardware.
94 * This data section is volatile.
95 *
96 * @{
97 */
98COMPILER_PACK_SET(1)
99COMPILER_WORD_ALIGNED
100union {
101 UsbDeviceDescriptor usb_endpoint_table[USB_EPT_NUM];
102} usb_descriptor_table;
103COMPILER_PACK_RESET()
104/** @} */
105
106/**
107 * \brief Local USB module instance
108 */
109static struct usb_module *_usb_instances;
110
111/* Device LPM callback variable */
112static uint32_t device_callback_lpm_wakeup_enable;
113
114/**
115 * \brief Device endpoint callback parameter variable, used to transfer info to UDD wrapper layer
116 */
117static struct usb_endpoint_callback_parameter ep_callback_para;
118
119/**
120 * \internal USB Device IRQ Mask Bits Map
121 */
122static const uint16_t _usb_device_irq_bits[USB_DEVICE_CALLBACK_N] = {
123 USB_DEVICE_INTFLAG_SOF,
124 USB_DEVICE_INTFLAG_EORST,
125 USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_EORSM | USB_DEVICE_INTFLAG_UPRSM,
126 USB_DEVICE_INTFLAG_RAMACER,
127 USB_DEVICE_INTFLAG_SUSPEND,
128 USB_DEVICE_INTFLAG_LPMNYET,
129 USB_DEVICE_INTFLAG_LPMSUSP,
130};
131
132/**
133 * \internal USB Device IRQ Mask Bits Map
134 */
135static const uint8_t _usb_endpoint_irq_bits[USB_DEVICE_EP_CALLBACK_N] = {
136 USB_DEVICE_EPINTFLAG_TRCPT_Msk,
137 USB_DEVICE_EPINTFLAG_TRFAIL_Msk,
138 USB_DEVICE_EPINTFLAG_RXSTP,
139 USB_DEVICE_EPINTFLAG_STALL_Msk
140};
141
142/**
143 * \brief Registers a USB device callback
144 *
145 * Registers a callback function which is implemented by the user.
146 *
147 * \note The callback must be enabled by \ref usb_device_enable_callback,
148 * in order for the interrupt handler to call it when the conditions for the
149 * callback type is met.
150 *
151 * \param[in] module_inst Pointer to USB software instance struct
152 * \param[in] callback_type Callback type given by an enum
153 * \param[in] callback_func Pointer to callback function
154 *
155 * \return Status of the registration operation.
156 * \retval STATUS_OK The callback was registered successfully.
157 */
158enum status_code usb_device_register_callback(struct usb_module *module_inst,
159 enum usb_device_callback callback_type,
160 usb_device_callback_t callback_func)
161{
162 /* Sanity check arguments */
163 Assert(module_inst);
164 Assert(callback_func);
165
166 /* Register callback function */
167 module_inst->device_callback[callback_type] = callback_func;
168
169 /* Set the bit corresponding to the callback_type */
170 module_inst->device_registered_callback_mask |= _usb_device_irq_bits[callback_type];
171
172 return STATUS_OK;
173}
174
175/**
176 * \brief Unregisters a USB device callback
177 *
178 * Unregisters an asynchronous callback implemented by the user. Removing it
179 * from the internal callback registration table.
180 *
181 * \param[in] module_inst Pointer to USB software instance struct
182 * \param[in] callback_type Callback type given by an enum
183 *
184 * \return Status of the de-registration operation.
185 * \retval STATUS_OK The callback was unregistered successfully.
186 */
187enum status_code usb_device_unregister_callback(struct usb_module *module_inst,
188 enum usb_device_callback callback_type)
189{
190 /* Sanity check arguments */
191 Assert(module_inst);
192
193 /* Unregister callback function */
194 module_inst->device_callback[callback_type] = NULL;
195
196 /* Clear the bit corresponding to the callback_type */
197 module_inst->device_registered_callback_mask &= ~_usb_device_irq_bits[callback_type];
198
199 return STATUS_OK;
200}
201
202/**
203 * \brief Enables USB device callback generation for a given type.
204 *
205 * Enables asynchronous callbacks for a given logical type.
206 * This must be called before USB device generate callback events.
207 *
208 * \param[in] module_inst Pointer to USB software instance struct
209 * \param[in] callback_type Callback type given by an enum
210 *
211 * \return Status of the callback enable operation.
212 * \retval STATUS_OK The callback was enabled successfully.
213 */
214enum status_code usb_device_enable_callback(struct usb_module *module_inst,
215 enum usb_device_callback callback_type)
216{
217 /* Sanity check arguments */
218 Assert(module_inst);
219 Assert(module_inst->hw);
220
221 /* clear related flag */
222 module_inst->hw->DEVICE.INTFLAG.reg = _usb_device_irq_bits[callback_type];
223
224 /* Enable callback */
225 module_inst->device_enabled_callback_mask |= _usb_device_irq_bits[callback_type];
226
227 module_inst->hw->DEVICE.INTENSET.reg = _usb_device_irq_bits[callback_type];
228
229 return STATUS_OK;
230}
231
232/**
233 * \brief Disables USB device callback generation for a given type.
234 *
235 * Disables asynchronous callbacks for a given logical type.
236 *
237 * \param[in] module_inst Pointer to USB software instance struct
238 * \param[in] callback_type Callback type given by an enum
239 *
240 * \return Status of the callback disable operation.
241 * \retval STATUS_OK The callback was disabled successfully.
242 */
243enum status_code usb_device_disable_callback(struct usb_module *module_inst,
244 enum usb_device_callback callback_type)
245{
246 /* Sanity check arguments */
247 Assert(module_inst);
248 Assert(module_inst->hw);
249
250 /* Disable callback */
251 module_inst->device_enabled_callback_mask &= ~_usb_device_irq_bits[callback_type];
252
253 module_inst->hw->DEVICE.INTENCLR.reg = _usb_device_irq_bits[callback_type];
254
255 return STATUS_OK;
256}
257
258/**
259 * \brief Registers a USB device endpoint callback
260 *
261 * Registers a callback function which is implemented by the user.
262 *
263 * \note The callback must be enabled by \ref usb_device_endpoint_enable_callback,
264 * in order for the interrupt handler to call it when the conditions for the
265 * callback type is met.
266 *
267 * \param[in] module_inst Pointer to USB software instance struct
268 * \param[in] ep_num Endpoint to configure
269 * \param[in] callback_type Callback type given by an enum
270 * \param[in] callback_func Pointer to callback function
271 *
272 * \return Status of the registration operation.
273 * \retval STATUS_OK The callback was registered successfully.
274 */
275enum status_code usb_device_endpoint_register_callback(
276 struct usb_module *module_inst, uint8_t ep_num,
277 enum usb_device_endpoint_callback callback_type,
278 usb_device_endpoint_callback_t callback_func)
279{
280 /* Sanity check arguments */
281 Assert(module_inst);
282 Assert(ep_num < USB_EPT_NUM);
283 Assert(callback_func);
284
285 /* Register callback function */
286 module_inst->device_endpoint_callback[ep_num][callback_type] = callback_func;
287
288 /* Set the bit corresponding to the callback_type */
289 module_inst->device_endpoint_registered_callback_mask[ep_num] |= _usb_endpoint_irq_bits[callback_type];
290
291 return STATUS_OK;
292}
293
294/**
295 * \brief Unregisters a USB device endpoint callback
296 *
297 * Unregisters an callback implemented by the user. Removing it
298 * from the internal callback registration table.
299 *
300 * \param[in] module_inst Pointer to USB software instance struct
301 * \param[in] ep_num Endpoint to configure
302 * \param[in] callback_type Callback type given by an enum
303 *
304 * \return Status of the de-registration operation.
305 * \retval STATUS_OK The callback was unregistered successfully.
306 */
307enum status_code usb_device_endpoint_unregister_callback(
308 struct usb_module *module_inst, uint8_t ep_num,
309 enum usb_device_endpoint_callback callback_type)
310{
311 /* Sanity check arguments */
312 Assert(module_inst);
313 Assert(ep_num < USB_EPT_NUM);
314
315 /* Unregister callback function */
316 module_inst->device_endpoint_callback[ep_num][callback_type] = NULL;
317
318 /* Clear the bit corresponding to the callback_type */
319 module_inst->device_endpoint_registered_callback_mask[ep_num] &= ~_usb_endpoint_irq_bits[callback_type];
320
321 return STATUS_OK;
322}
323
324/**
325 * \brief Enables USB device endpoint callback generation for a given type.
326 *
327 * Enables callbacks for a given logical type.
328 * This must be called before USB device pipe generate callback events.
329 *
330 * \param[in] module_inst Pointer to USB software instance struct
331 * \param[in] ep Endpoint to configure
332 * \param[in] callback_type Callback type given by an enum
333 *
334 * \return Status of the callback enable operation.
335 * \retval STATUS_OK The callback was enabled successfully.
336 */
337enum status_code usb_device_endpoint_enable_callback(
338 struct usb_module *module_inst, uint8_t ep,
339 enum usb_device_endpoint_callback callback_type)
340{
341 /* Sanity check arguments */
342 Assert(module_inst);
343 Assert(module_inst->hw);
344
345 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
346 Assert(ep_num < USB_EPT_NUM);
347
348 /* Enable callback */
349 module_inst->device_endpoint_enabled_callback_mask[ep_num] |= _usb_endpoint_irq_bits[callback_type];
350
351 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRCPT) {
352 if (ep_num == 0) { // control endpoint
353 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1;
354 } else if (ep & USB_EP_DIR_IN) {
355 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT1;
356 } else {
357 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0;
358 }
359 }
360
361 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL) {
362 if (ep_num == 0) { // control endpoint
363 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL0 | USB_DEVICE_EPINTENSET_TRFAIL1;
364 } else if (ep & USB_EP_DIR_IN) {
365 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL1;
366 } else {
367 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL0;
368 }
369 }
370
371 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_RXSTP) {
372 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_RXSTP;
373 }
374
375 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_STALL) {
376 if (ep & USB_EP_DIR_IN) {
377 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_STALL1;
378 } else {
379 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_STALL0;
380 }
381 }
382
383 return STATUS_OK;
384}
385
386/**
387 * \brief Disables USB device endpoint callback generation for a given type.
388 *
389 * Disables callbacks for a given logical type.
390 *
391 * \param[in] module_inst Pointer to USB software instance struct
392 * \param[in] ep Endpoint to configure
393 * \param[in] callback_type Callback type given by an enum
394 *
395 * \return Status of the callback disable operation.
396 * \retval STATUS_OK The callback was disabled successfully.
397 */
398enum status_code usb_device_endpoint_disable_callback(
399 struct usb_module *module_inst, uint8_t ep,
400 enum usb_device_endpoint_callback callback_type)
401{
402 /* Sanity check arguments */
403 Assert(module_inst);
404 Assert(module_inst->hw);
405
406 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
407 Assert(ep_num < USB_EPT_NUM);
408
409 /* Enable callback */
410 module_inst->device_endpoint_enabled_callback_mask[ep_num] &= ~_usb_endpoint_irq_bits[callback_type];
411
412 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRCPT) {
413 if (ep_num == 0) { // control endpoint
414 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRCPT0 | USB_DEVICE_EPINTENCLR_TRCPT1;
415 } else if (ep & USB_EP_DIR_IN) {
416 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRCPT1;
417 } else {
418 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRCPT0;
419 }
420 }
421
422 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL) {
423 if (ep_num == 0) { // control endpoint
424 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL0 | USB_DEVICE_EPINTENCLR_TRFAIL1;
425 } else if (ep & USB_EP_DIR_IN) {
426 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL1;
427 } else {
428 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL0;
429 }
430 }
431
432 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_RXSTP) {
433 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_RXSTP;
434 }
435
436 if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_STALL) {
437 if (ep & USB_EP_DIR_IN) {
438 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_STALL1;
439 } else {
440 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_STALL0;
441 }
442 }
443
444 return STATUS_OK;
445}
446
447/**
448 * \brief Initializes an USB device endpoint configuration structure to defaults.
449 *
450 * Initializes a given USB device endpoint configuration structure to a
451 * set of known default values. This function should be called on all new
452 * instances of these configuration structures before being modified by the
453 * user application.
454 *
455 * The default configuration is as follows:
456 * \li endpoint address is 0
457 * \li endpoint size is 8 bytes
458 * \li auto_zlp is false
459 * \li endpoint type is control
460 *
461 * \param[out] ep_config Configuration structure to initialize to default values
462 */
463void usb_device_endpoint_get_config_defaults(struct usb_device_endpoint_config *ep_config)
464{
465 /* Sanity check arguments */
466 Assert(ep_config);
467
468 /* Write default config to config struct */
469 ep_config->ep_address = 0;
470 ep_config->ep_size = USB_ENDPOINT_8_BYTE;
471 ep_config->auto_zlp = false;
472 ep_config->ep_type = USB_DEVICE_ENDPOINT_TYPE_CONTROL;
473}
474
475/**
476 * \brief Writes an USB device endpoint configuration to the hardware module.
477 *
478 * Writes out a given configuration of an USB device endpoint
479 * configuration to the hardware module. If the pipe is already configured,
480 * the new configuration will replace the existing one.
481 *
482 * \param[in] module_inst Pointer to USB software instance struct
483 * \param[in] ep_config Configuration settings for the endpoint
484 *
485 * \return Status of the device endpoint configuration operation
486 * \retval STATUS_OK The device endpoint was configured successfully
487 * \retval STATUS_ERR_DENIED The endpoint address is already configured
488 */
489enum status_code usb_device_endpoint_set_config(struct usb_module *module_inst,
490 struct usb_device_endpoint_config *ep_config)
491{
492 /* Sanity check arguments */
493 Assert(module_inst);
494 Assert(ep_config);
495
496 uint8_t ep_num = ep_config->ep_address & USB_EP_ADDR_MASK;
497 uint8_t ep_bank = (ep_config->ep_address & USB_EP_DIR_IN) ? 1 : 0;
498
499 switch (ep_config->ep_type) {
500 case USB_DEVICE_ENDPOINT_TYPE_DISABLE:
501 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0) | USB_DEVICE_EPCFG_EPTYPE1(0);
502 return STATUS_OK;
503
504 case USB_DEVICE_ENDPOINT_TYPE_CONTROL:
505 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0 && \
506 (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0) {
507 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
508 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
509 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
510 } else {
511 return STATUS_ERR_DENIED;
512 }
513 if (true == ep_config->auto_zlp) {
514 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
515 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
516 } else {
517 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
518 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
519 }
520 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.SIZE = ep_config->ep_size;
521 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.SIZE = ep_config->ep_size;
522 return STATUS_OK;
523
524 case USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS:
525 if (ep_bank) {
526 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
527 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(2);
528 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
529 } else {
530 return STATUS_ERR_DENIED;
531 }
532 } else {
533 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
534 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(2);
535 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
536 } else {
537 return STATUS_ERR_DENIED;
538 }
539 }
540 break;
541
542 case USB_DEVICE_ENDPOINT_TYPE_BULK:
543 if (ep_bank) {
544 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
545 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(3);
546 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
547 } else {
548 return STATUS_ERR_DENIED;
549 }
550 } else {
551 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
552 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(3);
553 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
554 } else {
555 return STATUS_ERR_DENIED;
556 }
557 }
558 break;
559
560 case USB_DEVICE_ENDPOINT_TYPE_INTERRUPT:
561 if (ep_bank) {
562 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
563 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(4);
564 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
565 } else {
566 return STATUS_ERR_DENIED;
567 }
568 } else {
569 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
570 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(4);
571 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
572 } else {
573 return STATUS_ERR_DENIED;
574 }
575 }
576 break;
577
578 default:
579 break;
580 }
581
582 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.bit.SIZE = ep_config->ep_size;
583
584 if (true == ep_config->auto_zlp) {
585 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
586 } else {
587 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
588 }
589
590 return STATUS_OK;
591}
592
593/**
594 * \brief Check if current endpoint is configured
595 *
596 * \param module_inst Pointer to USB software instance struct
597 * \param ep Endpoint address (direction & number)
598 *
599 * \return \c true if endpoint is configured and ready to use
600 */
601bool usb_device_endpoint_is_configured(struct usb_module *module_inst, uint8_t ep)
602{
603 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
604 uint8_t flag;
605
606 if (ep & USB_EP_DIR_IN) {
607 flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE1);
608 } else {
609 flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE0);
610 }
611 return ((enum usb_device_endpoint_type)(flag) != USB_DEVICE_ENDPOINT_TYPE_DISABLE);
612}
613
614
615/**
616 * \brief Abort ongoing job on the endpoint
617 *
618 * \param module_inst Pointer to USB software instance struct
619 * \param ep Endpoint address
620 */
621void usb_device_endpoint_abort_job(struct usb_module *module_inst, uint8_t ep)
622{
623 uint8_t ep_num;
624 ep_num = ep & USB_EP_ADDR_MASK;
625
626 // Stop transfer
627 if (ep & USB_EP_DIR_IN) {
628 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
629 // Eventually ack a transfer occur during abort
630 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
631 } else {
632 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
633 // Eventually ack a transfer occur during abort
634 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
635 }
636}
637
638/**
639 * \brief Check if endpoint is halted
640 *
641 * \param module_inst Pointer to USB software instance struct
642 * \param ep Endpoint address
643 *
644 * \return \c true if the endpoint is halted
645 */
646bool usb_device_endpoint_is_halted(struct usb_module *module_inst, uint8_t ep)
647{
648 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
649
650 if (ep & USB_EP_DIR_IN) {
651 return (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1);
652 } else {
653 return (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0);
654 }
655}
656
657/**
658 * \brief Halt the endpoint (send STALL)
659 *
660 * \param module_inst Pointer to USB software instance struct
661 * \param ep Endpoint address
662 */
663void usb_device_endpoint_set_halt(struct usb_module *module_inst, uint8_t ep)
664{
665 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
666
667 // Stall endpoint
668 if (ep & USB_EP_DIR_IN) {
669 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
670 } else {
671 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
672 }
673}
674
675/**
676 * \brief Clear endpoint halt state
677 *
678 * \param module_inst Pointer to USB software instance struct
679 * \param ep Endpoint address
680 */
681void usb_device_endpoint_clear_halt(struct usb_module *module_inst, uint8_t ep)
682{
683 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
684
685 if (ep & USB_EP_DIR_IN) {
686 if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) {
687 // Remove stall request
688 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
689 if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL1) {
690 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
691 // The Stall has occurred, then reset data toggle
692 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN;
693 }
694 }
695 } else {
696 if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) {
697 // Remove stall request
698 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
699 if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL0) {
700 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
701 // The Stall has occurred, then reset data toggle
702 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT;
703 }
704 }
705 }
706}
707
708/**
709 * \brief Start write buffer job on a endpoint
710 *
711 * \param module_inst Pointer to USB module instance
712 * \param ep_num Endpoint number
713 * \param pbuf Pointer to buffer
714 * \param buf_size Size of buffer
715 *
716 * \return Status of procedure
717 * \retval STATUS_OK Job started successfully
718 * \retval STATUS_ERR_DENIED Endpoint is not ready
719 */
720enum status_code usb_device_endpoint_write_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
721 uint8_t* pbuf, uint32_t buf_size)
722{
723 /* Sanity check arguments */
724 Assert(module_inst);
725 Assert(module_inst->hw);
726 Assert(ep_num < USB_EPT_NUM);
727
728 uint8_t flag;
729 flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE1);
730 if ((enum usb_device_endpoint_type)(flag) == USB_DEVICE_ENDPOINT_TYPE_DISABLE) {
731 return STATUS_ERR_DENIED;
732 };
733
734 /* get endpoint configuration from setting register */
735 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].ADDR.reg = (uint32_t)pbuf;
736 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
737 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = buf_size;
738 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
739
740 return STATUS_OK;
741}
742
743/**
744 * \brief Start read buffer job on a endpoint
745 *
746 * \param module_inst Pointer to USB module instance
747 * \param ep_num Endpoint number
748 * \param pbuf Pointer to buffer
749 * \param buf_size Size of buffer
750 *
751 * \return Status of procedure
752 * \retval STATUS_OK Job started successfully
753 * \retval STATUS_ERR_DENIED Endpoint is not ready
754 */
755enum status_code usb_device_endpoint_read_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
756 uint8_t* pbuf, uint32_t buf_size)
757{
758 /* Sanity check arguments */
759 Assert(module_inst);
760 Assert(module_inst->hw);
761 Assert(ep_num < USB_EPT_NUM);
762
763 uint8_t flag;
764 flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE0);
765 if ((enum usb_device_endpoint_type)(flag) == USB_DEVICE_ENDPOINT_TYPE_DISABLE) {
766 return STATUS_ERR_DENIED;
767 };
768
769 /* get endpoint configuration from setting register */
770 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].ADDR.reg = (uint32_t)pbuf;
771 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
772 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
773 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
774
775 return STATUS_OK;
776}
777
778/**
779 * \brief Start setup packet read job on a endpoint
780 *
781 * \param module_inst Pointer to USB device module instance
782 * \param pbuf Pointer to buffer
783 *
784 * \return Status of procedure
785 * \retval STATUS_OK Job started successfully
786 * \retval STATUS_ERR_DENIED Endpoint is not ready
787 */
788enum status_code usb_device_endpoint_setup_buffer_job(struct usb_module *module_inst,
789 uint8_t* pbuf)
790{
791 /* Sanity check arguments */
792 Assert(module_inst);
793 Assert(module_inst->hw);
794
795 /* get endpoint configuration from setting register */
796 usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].ADDR.reg = (uint32_t)pbuf;
797 usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
798 usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
799 module_inst->hw->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
800
801 return STATUS_OK;
802}
803
804static void _usb_device_interrupt_handler(void)
805{
806 uint16_t ep_inst;
807 uint16_t flags, flags_run;
808 ep_inst = _usb_instances->hw->DEVICE.EPINTSMRY.reg;
809
810 /* device interrupt */
811 if (0 == ep_inst) {
812 int i;
813
814 /* get interrupt flags */
815 flags = _usb_instances->hw->DEVICE.INTFLAG.reg;
816 flags_run = flags &
817 _usb_instances->device_enabled_callback_mask &
818 _usb_instances->device_registered_callback_mask;
819
820 for (i = 0; i < USB_DEVICE_CALLBACK_N; i ++) {
821 if (flags & _usb_device_irq_bits[i]) {
822 _usb_instances->hw->DEVICE.INTFLAG.reg =
823 _usb_device_irq_bits[i];
824 }
825 if (flags_run & _usb_device_irq_bits[i]) {
826 if (i == USB_DEVICE_CALLBACK_LPMSUSP) {
827 device_callback_lpm_wakeup_enable =
828 usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].EXTREG.bit.VARIABLE
829 & USB_LPM_ATTRIBUT_REMOTEWAKE_MASK;
830 }
831 (_usb_instances->device_callback[i])(_usb_instances, &device_callback_lpm_wakeup_enable);
832 }
833 }
834
835 } else {
836 /* endpoint interrupt */
837
838 for (uint8_t i = 0; i < USB_EPT_NUM; i++) {
839
840 if (ep_inst & (1 << i)) {
841 flags = _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg;
842 flags_run = flags &
843 _usb_instances->device_endpoint_enabled_callback_mask[i] &
844 _usb_instances->device_endpoint_registered_callback_mask[i];
845
846 // endpoint transfer stall interrupt
847 if (flags & USB_DEVICE_EPINTFLAG_STALL_Msk) {
848 if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL1) {
849 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
850 ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
851 } else if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL0) {
852 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
853 ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
854 }
855
856 if (flags_run & USB_DEVICE_EPINTFLAG_STALL_Msk) {
857 (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_STALL])(_usb_instances,&ep_callback_para);
858 }
859 return;
860 }
861
862 // endpoint received setup interrupt
863 if (flags & USB_DEVICE_EPINTFLAG_RXSTP) {
864 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
865 if(_usb_instances->device_endpoint_enabled_callback_mask[i] & _usb_endpoint_irq_bits[USB_DEVICE_ENDPOINT_CALLBACK_RXSTP]) {
866 ep_callback_para.received_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT);
867 (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_RXSTP])(_usb_instances,&ep_callback_para);
868 }
869 return;
870 }
871
872 // endpoint transfer complete interrupt
873 if (flags & USB_DEVICE_EPINTFLAG_TRCPT_Msk) {
874 if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1) {
875 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
876 ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
877 ep_callback_para.sent_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT);
878
879 } else if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0) {
880 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
881 ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
882 ep_callback_para.received_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT);
883 ep_callback_para.out_buffer_size = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE);
884 }
885 if(flags_run & USB_DEVICE_EPINTFLAG_TRCPT_Msk) {
886 (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_TRCPT])(_usb_instances,&ep_callback_para);
887 }
888 return;
889 }
890
891 // endpoint transfer fail interrupt
892 if (flags & USB_DEVICE_EPINTFLAG_TRFAIL_Msk) {
893 if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRFAIL1) {
894 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRFAIL1;
895 if (usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].STATUS_BK.reg & USB_DEVICE_STATUS_BK_ERRORFLOW) {
896 usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].STATUS_BK.reg &= ~USB_DEVICE_STATUS_BK_ERRORFLOW;
897 }
898 ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
899 if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1) {
900 return;
901 }
902 } else if(_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRFAIL0) {
903 _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRFAIL0;
904 if (usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].STATUS_BK.reg & USB_DEVICE_STATUS_BK_ERRORFLOW) {
905 usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].STATUS_BK.reg &= ~USB_DEVICE_STATUS_BK_ERRORFLOW;
906 }
907 ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
908 if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0) {
909 return;
910 }
911 }
912
913 if(flags_run & USB_DEVICE_EPINTFLAG_TRFAIL_Msk) {
914 (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL])(_usb_instances,&ep_callback_para);
915 }
916 return;
917 }
918 }
919 }
920 }
921}
922
923/**
924 * \brief Enable the USB module peripheral
925 *
926 * \param module_inst pointer to USB module instance
927 */
928void usb_enable(struct usb_module *module_inst)
929{
930 Assert(module_inst);
931 Assert(module_inst->hw);
932
933 module_inst->hw->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE;
934 while (module_inst->hw->DEVICE.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
935}
936
937/**
938 * \brief Disable the USB module peripheral
939 *
940 * \param module_inst pointer to USB module instance
941 */
942void usb_disable(struct usb_module *module_inst)
943{
944 Assert(module_inst);
945 Assert(module_inst->hw);
946
947 module_inst->hw->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_MASK;
948 module_inst->hw->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_MASK;
949 module_inst->hw->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE;
950 while (module_inst->hw->DEVICE.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
951}
952
953/**
954 * \brief Interrupt handler for the USB module.
955 */
956void USB_0_Handler(void)
957{
958 if (_usb_instances->hw->DEVICE.CTRLA.bit.MODE) {
959
960 } else {
961 /*device mode ISR */
962 _usb_device_interrupt_handler();
963 }
964}
965
966void USB_1_Handler(void)
967{
968 _usb_device_interrupt_handler();
969}
970
971void USB_2_Handler(void)
972{
973 _usb_device_interrupt_handler();
974}
975
976void USB_3_Handler(void)
977{
978 _usb_device_interrupt_handler();
979}
980
981/**
982 * \brief Get the default USB module settings
983 *
984 * \param[out] module_config Configuration structure to initialize to default values
985 */
986void usb_get_config_defaults(struct usb_config *module_config)
987{
988 Assert(module_config);
989
990 /* Sanity check arguments */
991 Assert(module_config);
992 /* Write default configuration to config struct */
993 module_config->select_host_mode = 0;
994 module_config->run_in_standby = 1;
995 module_config->source_generator = 0;
996 module_config->speed_mode = USB_SPEED_FULL;
997}
998
999#define NVM_USB_PAD_TRANSN_POS 45
1000#define NVM_USB_PAD_TRANSN_SIZE 5
1001#define NVM_USB_PAD_TRANSP_POS 50
1002#define NVM_USB_PAD_TRANSP_SIZE 5
1003#define NVM_USB_PAD_TRIM_POS 55
1004#define NVM_USB_PAD_TRIM_SIZE 3
1005
1006/**
1007 * \brief Initializes USB module instance
1008 *
1009 * Enables the clock and initializes the USB module, based on the given
1010 * configuration values.
1011 *
1012 * \param[in,out] module_inst Pointer to the software module instance struct
1013 * \param[in] hw Pointer to the USB hardware module
1014 * \param[in] module_config Pointer to the USB configuration options struct
1015 *
1016 * \return Status of the initialization procedure.
1017 *
1018 * \retval STATUS_OK The module was initialized successfully
1019 */
1020
1021#define GCLK_USB 10
1022
1023enum status_code usb_init(struct usb_module *module_inst, Usb *const hw,
1024 struct usb_config *module_config)
1025{
1026 /* Sanity check arguments */
1027 Assert(hw);
1028 Assert(module_inst);
1029 Assert(module_config);
1030
1031 uint32_t i,j;
1032 uint32_t pad_transn, pad_transp, pad_trim;
1033
1034 Gclk *pgclk = GCLK;
1035 Mclk *pmclk = MCLK;
1036 Port *pport = PORT;
1037 Oscctrl *posc = OSCCTRL;
1038
1039 _usb_instances = module_inst;
1040
1041 /* Associate the software module instance with the hardware module */
1042 module_inst->hw = hw;
1043
1044 //setup peripheral and synchronous bus clocks to USB
1045 pmclk->AHBMASK.bit.USB_ = 1;
1046 pmclk->APBBMASK.bit.USB_ = 1;
1047
1048 /* Set up the USB DP/DN pins */
1049 pport->Group[0].PMUX[12].reg = 0x77; //PA24, PA25, function column H for USB D-, D+
1050 pport->Group[0].PINCFG[24].bit.PMUXEN = 1;
1051 pport->Group[0].PINCFG[25].bit.PMUXEN = 1;
1052 pport->Group[1].PMUX[11].bit.PMUXE = 7; //PB22, function column H for USB SOF_1KHz output
1053 pport->Group[1].PINCFG[22].bit.PMUXEN = 1;
1054
1055 //configure and enable DFLL for USB clock recovery mode at 48MHz
1056 posc->DFLLCTRLA.bit.ENABLE = 0;
1057 while (posc->DFLLSYNC.bit.ENABLE);
1058 while (posc->DFLLSYNC.bit.DFLLCTRLB);
1059 posc->DFLLCTRLB.bit.USBCRM = 1;
1060 while (posc->DFLLSYNC.bit.DFLLCTRLB);
1061 posc->DFLLCTRLB.bit.MODE = 1;
1062 while (posc->DFLLSYNC.bit.DFLLCTRLB);
1063 posc->DFLLCTRLB.bit.QLDIS = 0;
1064 while (posc->DFLLSYNC.bit.DFLLCTRLB);
1065 posc->DFLLCTRLB.bit.CCDIS = 1;
1066 posc->DFLLMUL.bit.MUL = 0xbb80; //4800 x 1KHz
1067 while (posc->DFLLSYNC.bit.DFLLMUL);
1068 posc->DFLLCTRLA.bit.ENABLE = 1;
1069 while (posc->DFLLSYNC.bit.ENABLE);
1070
1071 /* Setup clock for module */
1072 pgclk->PCHCTRL[GCLK_USB].bit.GEN = 0;
1073 pgclk->PCHCTRL[GCLK_USB].bit.CHEN = 1;
1074
1075 /* Reset */
1076 hw->DEVICE.CTRLA.bit.SWRST = 1;
1077 while (hw->DEVICE.SYNCBUSY.bit.SWRST) {
1078 /* Sync wait */
1079 }
1080
1081 /* Change QOS values to have the best performance and correct USB behaviour */
1082 USB->DEVICE.QOSCTRL.bit.CQOS = 2;
1083 USB->DEVICE.QOSCTRL.bit.DQOS = 2;
1084
1085 /* Load Pad Calibration */
1086
1087 pad_transn = (USB_FUSES_TRANSN_ADDR >> USB_FUSES_TRANSN_Pos) & USB_FUSES_TRANSN_Msk;
1088 if (pad_transn == 0x1F) {
1089 pad_transn = 5;
1090 }
1091
1092 hw->DEVICE.PADCAL.bit.TRANSN = pad_transn;
1093
1094 pad_transp = (USB_FUSES_TRANSP_ADDR >> USB_FUSES_TRANSP_Pos) & USB_FUSES_TRANSP_Msk;
1095 if (pad_transp == 0x1F) {
1096 pad_transp = 29;
1097 }
1098
1099 hw->DEVICE.PADCAL.bit.TRANSP = pad_transp;
1100
1101 pad_trim = (USB_FUSES_TRIM_ADDR >> USB_FUSES_TRIM_Pos) & USB_FUSES_TRIM_Msk;
1102 if (pad_trim == 0x07) {
1103 pad_trim = 3;
1104 }
1105
1106 hw->DEVICE.PADCAL.bit.TRIM = pad_trim;
1107
1108 /* Set the configuration */
1109 hw->DEVICE.CTRLA.bit.MODE = module_config->select_host_mode;
1110 hw->DEVICE.CTRLA.bit.RUNSTDBY = module_config->run_in_standby;
1111 hw->DEVICE.DESCADD.reg = (uint32_t)(&usb_descriptor_table.usb_endpoint_table[0]);
1112 if (USB_SPEED_FULL == module_config->speed_mode) {
1113 module_inst->hw->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;
1114 } else if(USB_SPEED_LOW == module_config->speed_mode) {
1115 module_inst->hw->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val;
1116 }
1117
1118 memset((uint8_t *)(&usb_descriptor_table.usb_endpoint_table[0]), 0,
1119 sizeof(usb_descriptor_table.usb_endpoint_table));
1120
1121 /* device callback related */
1122 for (i = 0; i < USB_DEVICE_CALLBACK_N; i++) {
1123 module_inst->device_callback[i] = NULL;
1124 }
1125 for (i = 0; i < USB_EPT_NUM; i++) {
1126 for(j = 0; j < USB_DEVICE_EP_CALLBACK_N; j++) {
1127 module_inst->device_endpoint_callback[i][j] = NULL;
1128 }
1129 }
1130 module_inst->device_registered_callback_mask = 0;
1131 module_inst->device_enabled_callback_mask = 0;
1132 for (j = 0; j < USB_EPT_NUM; j++) {
1133 module_inst->device_endpoint_registered_callback_mask[j] = 0;
1134 module_inst->device_endpoint_enabled_callback_mask[j] = 0;
1135 }
1136
1137 /* Enable interrupts for this USB module */
1138 NVIC_EnableIRQ(USB_0_IRQn);
1139 NVIC_EnableIRQ(USB_2_IRQn);
1140 NVIC_EnableIRQ(USB_3_IRQn);
1141
1142 return STATUS_OK;
1143}
1144
diff --git a/tmk_core/protocol/arm_atsam/usb/usb.h b/tmk_core/protocol/arm_atsam/usb/usb.h
new file mode 100644
index 000000000..9a452881a
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb.h
@@ -0,0 +1,492 @@
1/**
2 * \file
3 *
4 * \brief SAM USB Driver
5 *
6 * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46#ifndef USB_H_INCLUDED
47#define USB_H_INCLUDED
48
49#ifdef __cplusplus
50extern "C" {
51#endif
52
53/**
54 * \defgroup asfdoc_sam0_usb_group SAM Universal Serial Bus (USB)
55 *
56 * The Universal Serial Bus (USB) module complies with the USB 2.1 specification.
57 *
58 * The following peripherals are used by this module:
59 * - USB (Universal Serial Bus)
60 *
61 * The following devices can use this module:
62 * - Atmel | SMART SAM D51
63 *
64 * The USB module covers following mode:
65 * \if USB_DEVICE_MODE
66 * - USB Device Mode
67 * \endif
68 * \if USB_HOST_MODE
69 * - USB Host Mode
70 * \endif
71 *
72 * The USB module covers following speed:
73 * \if USB_HS_MODE
74 * - USB High Speed (480Mbit/s)
75 * \endif
76 * - USB Full Speed (12Mbit/s)
77 * \if USB_LS_MODE
78 * - USB Low Speed (1.5Mbit/s)
79 * \endif
80 *
81 * \if USB_LPM_MODE
82 * The USB module supports Link Power Management (LPM-L1) protocol.
83 * \endif
84 *
85 * USB support needs whole set of enumeration process, to make the device
86 * recognizable and usable. The USB driver is designed to interface to the
87 * USB Stack in Atmel Software Framework (ASF).
88 *
89 * \if USB_DEVICE_MODE
90 * \section asfdoc_sam0_usb_device USB Device Mode
91 * The ASF USB Device Stack has defined the USB Device Driver (UDD) interface,
92 * to support USB device operations. The USB module device driver complies with
93 * this interface, so that the USB Device Stack can work based on the
94 * USB module.
95 *
96 * Refer to <a href="http://www.atmel.com/images/doc8360.pdf">
97 * "ASF - USB Device Stack"</a> for more details.
98 * \endif
99 *
100 * \if USB_HOST_MODE
101 * \section adfdoc_sam0_usb_host USB Host Mode
102 * The ASF USB Host Stack has defined the USB Host Driver (UHD) interface,
103 * to support USB host operations. The USB module host driver complies with
104 * this interface, so that the USB Host Stack can work based on the USB module.
105 *
106 * Refer to <a href="http://www.atmel.com/images/doc8486.pdf">
107 * "ASF - USB Host Stack"</a> for more details.
108 * \endif
109 */
110
111/** Enum for the speed status for the USB module */
112enum usb_speed {
113 USB_SPEED_LOW,
114 USB_SPEED_FULL,
115};
116
117/** Enum for the possible callback types for the USB in host module */
118enum usb_host_callback {
119 USB_HOST_CALLBACK_SOF,
120 USB_HOST_CALLBACK_RESET,
121 USB_HOST_CALLBACK_WAKEUP,
122 USB_HOST_CALLBACK_DNRSM,
123 USB_HOST_CALLBACK_UPRSM,
124 USB_HOST_CALLBACK_RAMACER,
125 USB_HOST_CALLBACK_CONNECT,
126 USB_HOST_CALLBACK_DISCONNECT,
127 USB_HOST_CALLBACK_N,
128};
129
130/** Enum for the possible callback types for the USB pipe in host module */
131enum usb_host_pipe_callback {
132 USB_HOST_PIPE_CALLBACK_TRANSFER_COMPLETE,
133 USB_HOST_PIPE_CALLBACK_ERROR,
134 USB_HOST_PIPE_CALLBACK_SETUP,
135 USB_HOST_PIPE_CALLBACK_STALL,
136 USB_HOST_PIPE_CALLBACK_N,
137};
138
139/**
140 * \brief Host pipe types.
141 */
142enum usb_host_pipe_type {
143 USB_HOST_PIPE_TYPE_DISABLE,
144 USB_HOST_PIPE_TYPE_CONTROL,
145 USB_HOST_PIPE_TYPE_ISO,
146 USB_HOST_PIPE_TYPE_BULK,
147 USB_HOST_PIPE_TYPE_INTERRUPT,
148 USB_HOST_PIPE_TYPE_EXTENDED,
149};
150
151/**
152 * \brief Host pipe token types.
153 */
154enum usb_host_pipe_token {
155 USB_HOST_PIPE_TOKEN_SETUP,
156 USB_HOST_PIPE_TOKEN_IN,
157 USB_HOST_PIPE_TOKEN_OUT,
158};
159
160/**
161 * \brief Enumeration for the possible callback types for the USB in device module
162 */
163enum usb_device_callback {
164 USB_DEVICE_CALLBACK_SOF,
165 USB_DEVICE_CALLBACK_RESET,
166 USB_DEVICE_CALLBACK_WAKEUP,
167 USB_DEVICE_CALLBACK_RAMACER,
168 USB_DEVICE_CALLBACK_SUSPEND,
169 USB_DEVICE_CALLBACK_LPMNYET,
170 USB_DEVICE_CALLBACK_LPMSUSP,
171 USB_DEVICE_CALLBACK_N,
172};
173
174/**
175 * \brief Enumeration for the possible callback types for the USB endpoint in device module
176 */
177enum usb_device_endpoint_callback {
178 USB_DEVICE_ENDPOINT_CALLBACK_TRCPT,
179 USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL,
180 USB_DEVICE_ENDPOINT_CALLBACK_RXSTP,
181 USB_DEVICE_ENDPOINT_CALLBACK_STALL,
182 USB_DEVICE_EP_CALLBACK_N,
183};
184
185/**
186 * \brief Device Endpoint types.
187 */
188enum usb_device_endpoint_type {
189 USB_DEVICE_ENDPOINT_TYPE_DISABLE,
190 USB_DEVICE_ENDPOINT_TYPE_CONTROL,
191 USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS,
192 USB_DEVICE_ENDPOINT_TYPE_BULK,
193 USB_DEVICE_ENDPOINT_TYPE_INTERRUPT,
194};
195
196/**
197 * \brief Endpoint Size
198 */
199enum usb_endpoint_size {
200 USB_ENDPOINT_8_BYTE,
201 USB_ENDPOINT_16_BYTE,
202 USB_ENDPOINT_32_BYTE,
203 USB_ENDPOINT_64_BYTE,
204 USB_ENDPOINT_128_BYTE,
205 USB_ENDPOINT_256_BYTE,
206 USB_ENDPOINT_512_BYTE,
207 USB_ENDPOINT_1023_BYTE,
208};
209
210/**
211 * \brief Link Power Management Handshake.
212 */
213enum usb_device_lpm_mode {
214 USB_DEVICE_LPM_NOT_SUPPORT,
215 USB_DEVICE_LPM_ACK,
216 USB_DEVICE_LPM_NYET,
217};
218
219/**
220 * \brief Module structure
221 */
222struct usb_module;
223
224/**
225 * \name Host Callback Functions Types
226 * @{
227 */
228typedef void (*usb_host_callback_t)(struct usb_module *module_inst);
229typedef void (*usb_host_pipe_callback_t)(struct usb_module *module_inst, void *);
230/** @} */
231
232/**
233 * \name Device Callback Functions Types
234 * @{
235 */
236typedef void (*usb_device_callback_t)(struct usb_module *module_inst, void* pointer);
237typedef void (*usb_device_endpoint_callback_t)(struct usb_module *module_inst, void* pointer);
238/** @} */
239
240/** USB configurations */
241struct usb_config {
242 /** \c true for host, \c false for device. */
243 bool select_host_mode;
244 /** When \c true the module is enabled during standby. */
245 bool run_in_standby;
246 /** Generic Clock Generator source channel. */
247 // enum gclk_generator source_generator;
248 uint8_t source_generator;
249 /** Speed mode */
250 //enum usb_speed speed_mode;
251 uint8_t speed_mode;
252};
253
254/**
255 * \brief USB software module instance structure.
256 *
257 * USB software module instance structure, used to retain software state
258 * information of an associated hardware module instance.
259 *
260 */
261struct usb_module {
262 /** Hardware module pointer of the associated USB peripheral. */
263 Usb *hw;
264
265 /** Array to store device related callback functions */
266 usb_device_callback_t device_callback[USB_DEVICE_CALLBACK_N];
267 usb_device_endpoint_callback_t device_endpoint_callback[USB_EPT_NUM][USB_DEVICE_EP_CALLBACK_N];
268 /** Bit mask for device callbacks registered */
269 uint16_t device_registered_callback_mask;
270 /** Bit mask for device callbacks enabled */
271 uint16_t device_enabled_callback_mask;
272 /** Bit mask for device endpoint callbacks registered */
273 uint8_t device_endpoint_registered_callback_mask[USB_EPT_NUM];
274 /** Bit mask for device endpoint callbacks enabled */
275 uint8_t device_endpoint_enabled_callback_mask[USB_EPT_NUM];
276};
277
278/** USB device endpoint configurations */
279struct usb_device_endpoint_config {
280 /** device address */
281 uint8_t ep_address;
282 /** endpoint size */
283 enum usb_endpoint_size ep_size;
284 /** automatic zero length packet mode, \c true to enable */
285 bool auto_zlp;
286 /** type of endpoint with Bank */
287 enum usb_device_endpoint_type ep_type;
288};
289
290/** USB device endpoint callback status parameter structure */
291struct usb_endpoint_callback_parameter {
292 uint16_t received_bytes;
293 uint16_t sent_bytes;
294 uint16_t out_buffer_size;
295 uint8_t endpoint_address;
296};
297
298void usb_enable(struct usb_module *module_inst);
299void usb_disable(struct usb_module *module_inst);
300
301/**
302 * \brief Get the status of USB module's state machine
303 *
304 * \param module_inst Pointer to USB module instance
305 */
306static inline uint8_t usb_get_state_machine_status(struct usb_module *module_inst)
307{
308 /* Sanity check arguments */
309 Assert(module_inst);
310 Assert(module_inst->hw);
311
312 return module_inst->hw->DEVICE.FSMSTATUS.reg;
313}
314
315void usb_get_config_defaults(struct usb_config *module_config);
316enum status_code usb_init(struct usb_module *module_inst, Usb *const hw,
317 struct usb_config *module_config);
318
319/**
320 * \brief Attach USB device to the bus
321 *
322 * \param module_inst Pointer to USB device module instance
323 */
324static inline void usb_device_attach(struct usb_module *module_inst)
325{
326 module_inst->hw->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH;
327}
328
329/**
330 * \brief Detach USB device from the bus
331 *
332 * \param module_inst Pointer to USB device module instance
333 */
334static inline void usb_device_detach(struct usb_module *module_inst)
335{
336 module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_DETACH;
337}
338
339/**
340 * \brief Get the speed mode of USB device
341 *
342 * \param module_inst Pointer to USB device module instance
343 * \return USB Speed mode (\ref usb_speed).
344 */
345static inline enum usb_speed usb_device_get_speed(struct usb_module *module_inst)
346{
347 if (!(module_inst->hw->DEVICE.STATUS.reg & USB_DEVICE_STATUS_SPEED_Msk)) {
348 return USB_SPEED_FULL;
349 } else {
350 return USB_SPEED_LOW;
351 }
352}
353
354/**
355 * \brief Get the address of USB device
356 *
357 * \param module_inst Pointer to USB device module instance
358 * \return USB device address value.
359 */
360static inline uint8_t usb_device_get_address(struct usb_module *module_inst)
361{
362 return ((uint8_t)(module_inst->hw->DEVICE.DADD.bit.DADD));
363}
364
365/**
366 * \brief Set the speed mode of USB device
367 *
368 * \param module_inst Pointer to USB device module instance
369 * \param address USB device address value
370 */
371static inline void usb_device_set_address(struct usb_module *module_inst, uint8_t address)
372{
373 module_inst->hw->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | address;
374}
375
376/**
377 * \brief Get the frame number of USB device
378 *
379 * \param module_inst Pointer to USB device module instance
380 * \return USB device frame number value.
381 */
382static inline uint16_t usb_device_get_frame_number(struct usb_module *module_inst)
383{
384 return ((uint16_t)(module_inst->hw->DEVICE.FNUM.bit.FNUM));
385}
386
387/**
388 * \brief Get the micro-frame number of USB device
389 *
390 * \param module_inst Pointer to USB device module instance
391 * \return USB device micro-frame number value.
392 */
393static inline uint16_t usb_device_get_micro_frame_number(struct usb_module *module_inst)
394{
395 return ((uint16_t)(module_inst->hw->DEVICE.FNUM.reg));
396}
397
398/**
399 * \brief USB device send the resume wakeup
400 *
401 * \param module_inst Pointer to USB device module instance
402 */
403static inline void usb_device_send_remote_wake_up(struct usb_module *module_inst)
404{
405 module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_UPRSM;
406}
407
408/**
409 * \brief USB device set the LPM mode
410 *
411 * \param module_inst Pointer to USB device module instance
412 * \param lpm_mode LPM mode
413 */
414static inline void usb_device_set_lpm_mode(struct usb_module *module_inst,
415 enum usb_device_lpm_mode lpm_mode)
416{
417 module_inst->hw->DEVICE.CTRLB.bit.LPMHDSK = lpm_mode;
418}
419
420/**
421 * \name USB Device Callback Management
422 * @{
423 */
424enum status_code usb_device_register_callback(struct usb_module *module_inst,
425 enum usb_device_callback callback_type,
426 usb_device_callback_t callback_func);
427enum status_code usb_device_unregister_callback(struct usb_module *module_inst,
428 enum usb_device_callback callback_type);
429enum status_code usb_device_enable_callback(struct usb_module *module_inst,
430 enum usb_device_callback callback_type);
431enum status_code usb_device_disable_callback(struct usb_module *module_inst,
432 enum usb_device_callback callback_type);
433/** @} */
434
435/**
436 * \name USB Device Endpoint Configuration
437 * @{
438 */
439void usb_device_endpoint_get_config_defaults(struct usb_device_endpoint_config *ep_config);
440enum status_code usb_device_endpoint_set_config(struct usb_module *module_inst,
441 struct usb_device_endpoint_config *ep_config);
442bool usb_device_endpoint_is_configured(struct usb_module *module_inst, uint8_t ep);
443/** @} */
444
445/**
446 * \name USB Device Endpoint Callback Management
447 * @{
448 */
449enum status_code usb_device_endpoint_register_callback(
450 struct usb_module *module_inst, uint8_t ep_num,
451 enum usb_device_endpoint_callback callback_type,
452 usb_device_endpoint_callback_t callback_func);
453enum status_code usb_device_endpoint_unregister_callback(
454 struct usb_module *module_inst, uint8_t ep_num,
455 enum usb_device_endpoint_callback callback_type);
456enum status_code usb_device_endpoint_enable_callback(
457 struct usb_module *module_inst, uint8_t ep,
458 enum usb_device_endpoint_callback callback_type);
459enum status_code usb_device_endpoint_disable_callback(
460 struct usb_module *module_inst, uint8_t ep,
461 enum usb_device_endpoint_callback callback_type);
462/** @} */
463
464/**
465 * \name USB Device Endpoint Job Management
466 * @{
467 */
468enum status_code usb_device_endpoint_write_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
469 uint8_t* pbuf, uint32_t buf_size);
470enum status_code usb_device_endpoint_read_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
471 uint8_t* pbuf, uint32_t buf_size);
472enum status_code usb_device_endpoint_setup_buffer_job(struct usb_module *module_inst,
473 uint8_t* pbuf);
474void usb_device_endpoint_abort_job(struct usb_module *module_inst, uint8_t ep);
475/** @} */
476
477/**
478 * \name USB Device Endpoint Operations
479 * @{
480 */
481
482bool usb_device_endpoint_is_halted(struct usb_module *module_inst, uint8_t ep);
483void usb_device_endpoint_set_halt(struct usb_module *module_inst, uint8_t ep);
484void usb_device_endpoint_clear_halt(struct usb_module *module_inst, uint8_t ep);
485
486/** @} */
487
488#ifdef __cplusplus
489}
490#endif
491
492#endif /* USB_H_INCLUDED */
diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.c b/tmk_core/protocol/arm_atsam/usb/usb2422.c
new file mode 100644
index 000000000..7c78e41d4
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb2422.c
@@ -0,0 +1,412 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19#include <string.h>
20
21Usb2422 USB2422_shadow;
22unsigned char i2c0_buf[34];
23
24const uint16_t MFRNAME[] = { 'M','a','s','s','d','r','o','p',' ','I','n','c','.' }; //Massdrop Inc.
25const uint16_t PRDNAME[] = { 'M','a','s','s','d','r','o','p',' ','H','u','b' }; //Massdrop Hub
26#ifndef MD_BOOTLOADER
27//Serial number reported stops before first found space character or at last found character
28const uint16_t SERNAME[] = { 'U','n','a','v','a','i','l','a','b','l','e' }; //Unavailable
29#else
30//In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
31//The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
32//Serial number reported stops before first found space character or when max size is reached
33__attribute__((__aligned__(4)))
34const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = { 'M','D','H','U','B','B','O','O','T','L','0','0','0','0','0','0','0','0','0','0' };
35//NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
36// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
37#endif //MD_BOOTLOADER
38
39uint8_t usb_host_port;
40
41#ifndef MD_BOOTLOADER
42
43uint8_t usb_extra_state;
44uint8_t usb_extra_manual;
45uint8_t usb_gcr_auto;
46
47#endif //MD_BOOTLOADER
48
49uint16_t adc_extra;
50
51void USB_write2422_block(void)
52{
53 unsigned char *dest = i2c0_buf;
54 unsigned char *src;
55 unsigned char *base = (unsigned char *)&USB2422_shadow;
56
57 DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
58
59 for (src = base; src < base + 256; src += 32)
60 {
61 dest[0] = src - base;
62 dest[1] = 32;
63 memcpy(&dest[2], src, 32);
64 i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
65 SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
66 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); }
67 CLK_delay_us(100);
68 }
69
70 DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
71}
72
73void USB2422_init(void)
74{
75 Gclk *pgclk = GCLK;
76 Mclk *pmclk = MCLK;
77 Port *pport = PORT;
78 Oscctrl *posc = OSCCTRL;
79 Usb *pusb = USB;
80 Srdata_t *pspi = &srdata;
81
82 DBGC(DC_USB2422_INIT_BEGIN);
83
84 while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB2422_INIT_WAIT_5V_LOW); }
85
86 //setup peripheral and synchronous bus clocks to USB
87 pgclk->PCHCTRL[10].bit.GEN = 0;
88 pgclk->PCHCTRL[10].bit.CHEN = 1;
89 pmclk->AHBMASK.bit.USB_ = 1;
90 pmclk->APBBMASK.bit.USB_ = 1;
91
92 //setup port pins for D-, D+, and SOF_1KHZ
93 pport->Group[0].PMUX[12].reg = 0x77; //PA24, PA25, function column H for USB D-, D+
94 pport->Group[0].PINCFG[24].bit.PMUXEN = 1;
95 pport->Group[0].PINCFG[25].bit.PMUXEN = 1;
96 pport->Group[1].PMUX[11].bit.PMUXE = 7; //PB22, function column H for USB SOF_1KHz output
97 pport->Group[1].PINCFG[22].bit.PMUXEN = 1;
98
99 //configure and enable DFLL for USB clock recovery mode at 48MHz
100 posc->DFLLCTRLA.bit.ENABLE = 0;
101 while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_DISABLING); }
102 while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1); }
103 posc->DFLLCTRLB.bit.USBCRM = 1;
104 while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2); }
105 posc->DFLLCTRLB.bit.MODE = 1;
106 while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3); }
107 posc->DFLLCTRLB.bit.QLDIS = 0;
108 while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4); }
109 posc->DFLLCTRLB.bit.CCDIS = 1;
110 posc->DFLLMUL.bit.MUL = 0xBB80; //4800 x 1KHz
111 while (posc->DFLLSYNC.bit.DFLLMUL) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLMUL); }
112 posc->DFLLCTRLA.bit.ENABLE = 1;
113 while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_ENABLING); }
114
115 pusb->DEVICE.CTRLA.bit.SWRST = 1;
116 while (pusb->DEVICE.SYNCBUSY.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_SYNC_SWRST); }
117 while (pusb->DEVICE.CTRLA.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_WAIT_SWRST); }
118 //calibration from factory presets
119 pusb->DEVICE.PADCAL.bit.TRANSN = (USB_FUSES_TRANSN_ADDR >> USB_FUSES_TRANSN_Pos) & USB_FUSES_TRANSN_Msk;
120 pusb->DEVICE.PADCAL.bit.TRANSP = (USB_FUSES_TRANSP_ADDR >> USB_FUSES_TRANSP_Pos) & USB_FUSES_TRANSP_Msk;
121 pusb->DEVICE.PADCAL.bit.TRIM = (USB_FUSES_TRIM_ADDR >> USB_FUSES_TRIM_Pos) & USB_FUSES_TRIM_Msk;
122 //device mode, enabled
123 pusb->DEVICE.CTRLB.bit.SPDCONF = 0; //full speed
124 pusb->DEVICE.CTRLA.bit.MODE = 0;
125 pusb->DEVICE.CTRLA.bit.ENABLE = 1;
126 while (pusb->DEVICE.SYNCBUSY.bit.ENABLE) { DBGC(DC_USB2422_INIT_USB_SYNC_ENABLING); }
127
128 pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
129 pusb->DEVICE.QOSCTRL.bit.CQOS = 2;
130
131 pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1;
132
133 i2c0_init(); //IC2 clk must be high at USB2422 reset release time to signal SMB configuration
134
135 pspi->bit.HUB_CONNECT = 1; //connect signal
136 pspi->bit.HUB_RESET_N = 1; //reset high
137 SPI_WriteSRData();
138
139 CLK_delay_us(100);
140
141#ifndef MD_BOOTLOADER
142
143 usb_extra_manual = 0;
144 usb_gcr_auto = 1;
145
146#endif //MD_BOOTLOADER
147
148 DBGC(DC_USB2422_INIT_COMPLETE);
149}
150
151void USB_reset(void)
152{
153 Srdata_t *pspi = &srdata;
154
155 DBGC(DC_USB_RESET_BEGIN);
156
157 //pulse reset for at least 1 usec
158 pspi->bit.HUB_RESET_N = 0; //reset low
159 SPI_WriteSRData();
160 CLK_delay_us(1);
161 pspi->bit.HUB_RESET_N = 1; //reset high to run
162 SPI_WriteSRData();
163 CLK_delay_us(1);
164
165 DBGC(DC_USB_RESET_COMPLETE);
166}
167
168void USB_configure(void)
169{
170 Usb2422 *pusb2422 = &USB2422_shadow;
171 memset(pusb2422, 0, sizeof(Usb2422));
172
173 uint16_t *serial_use = (uint16_t *)SERNAME; //Default to use SERNAME from this file
174 uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); //Default to use SERNAME from this file
175#ifndef MD_BOOTLOADER
176 uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
177#else //MD_BOOTLOADER
178 uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
179#endif //MD_BOOTLOADER
180 uint32_t serial_address = *(uint32_t *)serial_ptrloc; //Address of bootloader's serial number if available
181
182 DBGC(DC_USB_CONFIGURE_BEGIN);
183
184 if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
185 {
186 if ((serial_address & 0xFF) % 4 == 0) //Check alignment
187 {
188 serial_use = (uint16_t *)(serial_address);
189 serial_length = 0;
190 while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
191 serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
192 {
193 serial_length++;
194 DBGC(DC_USB_CONFIGURE_GET_SERIAL);
195 }
196 }
197 }
198
199 //configure Usb2422 registers
200 pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
201 pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
202 pusb2422->DID.reg = 0x0101; // BCD 01.01
203 pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
204 pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
205 //pusb2422->CFG2.bit.COMPOUND = 0; // compound device
206 pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
207 //pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
208 pusb2422->MAXPB.reg = 20; // 0mA
209 pusb2422->HCMCB.reg = 20; // 0mA
210 pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
211 pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
212 pusb2422->SERSL.reg = serial_length;
213 memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
214 memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
215 memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
216 //pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
217 //pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
218 //pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
219 pusb2422->STCD.bit.USB_ATTACH = 1;
220 USB_write2422_block();
221
222 adc_extra = 0;
223
224 DBGC(DC_USB_CONFIGURE_COMPLETE);
225}
226
227uint16_t USB_active(void)
228{
229 return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0;
230}
231
232void USB_set_host_by_voltage(void)
233{
234 //UP is upstream device (HOST)
235 //DN1 is downstream device (EXTRA)
236 //DN2 is keyboard (KEYB)
237
238 DBGC(DC_USB_SET_HOST_BY_VOLTAGE_BEGIN);
239
240 usb_host_port = USB_HOST_PORT_UNKNOWN;
241#ifndef MD_BOOTLOADER
242 usb_extra_state = USB_EXTRA_STATE_UNKNOWN;
243#endif //MD_BOOTLOADER
244 srdata.bit.SRC_1 = 1; //USBC-1 available for test
245 srdata.bit.SRC_2 = 1; //USBC-2 available for test
246 srdata.bit.E_UP_N = 1; //HOST disable
247 srdata.bit.E_DN1_N = 1; //EXTRA disable
248 srdata.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
249 srdata.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
250
251 SPI_WriteSRData();
252
253 CLK_delay_ms(250);
254
255 while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); }
256
257 v_con_1 = adc_get(ADC_CON1);
258 v_con_2 = adc_get(ADC_CON2);
259
260 v_con_1_boot = v_con_1;
261 v_con_2_boot = v_con_2;
262
263 if (v_con_1 > v_con_2)
264 {
265 srdata.bit.S_UP = 0; //HOST to USBC-1
266 srdata.bit.S_DN1 = 1; //EXTRA to USBC-2
267 srdata.bit.SRC_1 = 1; //HOST on USBC-1
268 srdata.bit.SRC_2 = 0; //EXTRA available on USBC-2
269
270 srdata.bit.E_VBUS_1 = 1; //USBC-1 enable full power I/O
271 srdata.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
272
273 SPI_WriteSRData();
274
275 srdata.bit.E_UP_N = 0; //HOST enable
276
277 SPI_WriteSRData();
278
279 usb_host_port = USB_HOST_PORT_1;
280 }
281 else
282 {
283 srdata.bit.S_UP = 1; //EXTRA to USBC-1
284 srdata.bit.S_DN1 = 0; //HOST to USBC-2
285 srdata.bit.SRC_1 = 0; //EXTRA available on USBC-1
286 srdata.bit.SRC_2 = 1; //HOST on USBC-2
287
288 srdata.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
289 srdata.bit.E_VBUS_2 = 1; //USBC-2 enable full power I/O
290
291 SPI_WriteSRData();
292
293 srdata.bit.E_UP_N = 0; //HOST enable
294
295 SPI_WriteSRData();
296
297 usb_host_port = USB_HOST_PORT_2;
298 }
299
300#ifndef MD_BOOTLOADER
301 usb_extra_state = USB_EXTRA_STATE_DISABLED;
302#endif //MD_BOOTLOADER
303
304 USB_reset();
305 USB_configure();
306
307 DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
308}
309
310uint8_t USB2422_Port_Detect_Init(void)
311{
312 uint32_t port_detect_retry_ms;
313 uint32_t tmod;
314
315 DBGC(DC_PORT_DETECT_INIT_BEGIN);
316
317 USB_set_host_by_voltage();
318
319 port_detect_retry_ms = CLK_get_ms() + PORT_DETECT_RETRY_INTERVAL;
320
321 while (!USB_active())
322 {
323 tmod = CLK_get_ms() % PORT_DETECT_RETRY_INTERVAL;
324
325 if (v_con_1 > v_con_2) //Values updated from USB_set_host_by_voltage();
326 {
327 //1 flash for port 1 detected
328 if (tmod > 500 && tmod < 600) { led_on; }
329 else { led_off; }
330 }
331 else if (v_con_2 > v_con_1) //Values updated from USB_set_host_by_voltage();
332 {
333 //2 flash for port 2 detected
334 if (tmod > 500 && tmod < 600) { led_on; }
335 else if (tmod > 700 && tmod < 800) { led_on; }
336 else { led_off; }
337 }
338
339 if (CLK_get_ms() > port_detect_retry_ms)
340 {
341 DBGC(DC_PORT_DETECT_INIT_FAILED);
342 return 0;
343 }
344 }
345
346 DBGC(DC_PORT_DETECT_INIT_COMPLETE);
347
348 return 1;
349}
350
351#ifndef MD_BOOTLOADER
352
353void USB_ExtraSetState(uint8_t state)
354{
355 uint8_t state_save = state;
356
357 if (state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
358 state = USB_EXTRA_STATE_DISABLED;
359
360 if (usb_host_port == USB_HOST_PORT_1) srdata.bit.E_VBUS_2 = state;
361 else if (usb_host_port == USB_HOST_PORT_2) srdata.bit.E_VBUS_1 = state;
362 else return;
363
364 srdata.bit.E_DN1_N = !state;
365 SPI_WriteSRData();
366
367 usb_extra_state = state_save;
368
369 if (usb_extra_state == USB_EXTRA_STATE_ENABLED) CDC_print("USB: Extra enabled\r\n");
370 else if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
371 {
372 CDC_print("USB: Extra disabled\r\n");
373 if (led_animation_breathing) gcr_breathe = gcr_desired;
374 }
375 else if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) CDC_print("USB: Extra disabled until replug\r\n");
376 else CDC_print("USB: Extra state unknown\r\n");
377}
378
379void USB_HandleExtraDevice(void)
380{
381 uint16_t adcval;
382
383 if (usb_host_port == USB_HOST_PORT_1) adcval = adc_get(ADC_CON2);
384 else if (usb_host_port == USB_HOST_PORT_2) adcval = adc_get(ADC_CON1);
385 else return;
386
387 adc_extra = adc_extra * 0.9 + adcval * 0.1;
388
389 //Check for a forced disable state (such as overload prevention)
390 if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
391 {
392 //Detect unplug and reset state to disabled
393 if (adc_extra > USB_EXTRA_ADC_THRESHOLD) usb_extra_state = USB_EXTRA_STATE_DISABLED;
394
395 return; //Return even if unplug detected
396 }
397
398 if (usb_extra_manual)
399 {
400 if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
401 USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
402
403 return;
404 }
405
406 //dpf("a %i %i\r\n",adcval, adc_extra);
407 if (usb_extra_state == USB_EXTRA_STATE_DISABLED && adc_extra < USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
408 else if (usb_extra_state == USB_EXTRA_STATE_ENABLED && adc_extra > USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_DISABLED);
409}
410
411#endif //MD_BOOTLOADER
412
diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.h b/tmk_core/protocol/arm_atsam/usb/usb2422.h
new file mode 100644
index 000000000..6c763dd8c
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb2422.h
@@ -0,0 +1,405 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _USB2422_H_
19#define _USB2422_H_
20
21#define USB2422_ALT67_1P0
22#define REV_USB2422 0x100
23
24#define USB2422_ADDR 0x58 //I2C device address, one instance
25
26#define USB2422_HUB_ACTIVE_GROUP 0 //PA
27#define USB2422_HUB_ACTIVE_PIN 18 //18
28
29/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */
30#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
31typedef union {
32 struct {
33 uint16_t VID_LSB : 8;
34 uint16_t VID_MSB : 8;
35 } bit; /*!< Structure used for bit access */
36 uint16_t reg; /*!< Type used for register access */
37} USB2422_VID_Type;
38#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
39
40/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */
41#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
42typedef union {
43 struct {
44 uint16_t PID_LSB : 8;
45 uint16_t PID_MSB : 8;
46 } bit; /*!< Structure used for bit access */
47 uint16_t reg; /*!< Type used for register access */
48} USB2422_PID_Type;
49#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
50
51/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */
52#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
53typedef union {
54 struct {
55 uint16_t DID_LSB : 8;
56 uint16_t DID_MSB : 8;
57 } bit; /*!< Structure used for bit access */
58 uint16_t reg; /*!< Type used for register access */
59} USB2422_DID_Type;
60#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
61
62/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */
63#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
64typedef union {
65 struct {
66 uint8_t PORT_PWR : 1;
67 uint8_t CURRENT_SNS : 2;
68 uint8_t EOP_DISABLE : 1;
69 uint8_t MTT_ENABLE : 1;
70 uint8_t HS_DISABLE :1;
71 uint8_t :1;
72 uint8_t SELF_BUS_PWR : 1;
73 } bit; /*!< Structure used for bit access */
74 uint8_t reg; /*!< Type used for register access */
75} USB2422_CFG1_Type;
76#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
77
78/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */
79#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
80typedef union {
81 struct {
82 uint8_t : 3;
83 uint8_t COMPOUND : 1;
84 uint8_t OC_TIMER :2;
85 uint8_t :1;
86 uint8_t DYNAMIC : 1;
87 } bit; /*!< Structure used for bit access */
88 uint8_t reg; /*!< Type used for register access */
89} USB2422_CFG2_Type;
90#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
91
92/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */
93#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
94typedef union {
95 struct {
96 uint8_t STRING_EN : 1;
97 uint8_t :2;
98 uint8_t PRTMAP_EN :1;
99 uint8_t : 4;
100 } bit; /*!< Structure used for bit access */
101 uint8_t reg; /*!< Type used for register access */
102} USB2422_CFG3_Type;
103#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
104
105/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */
106#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
107typedef union {
108 struct {
109 uint8_t : 5;
110 uint8_t PORT2_NR :1;
111 uint8_t PORT1_NR :1;
112 uint8_t : 1;
113 } bit; /*!< Structure used for bit access */
114 uint8_t reg; /*!< Type used for register access */
115} USB2422_NRD_Type;
116#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
117
118/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */
119#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
120typedef union {
121 struct {
122 uint8_t : 1;
123 uint8_t PORT1_DIS :1;
124 uint8_t PORT2_DIS :1;
125 uint8_t : 5;
126 } bit; /*!< Structure used for bit access */
127 uint8_t reg; /*!< Type used for register access */
128} USB2422_PDS_Type;
129#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
130
131/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */
132#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
133typedef union {
134 struct {
135 uint8_t : 1;
136 uint8_t PORT1_DIS :1;
137 uint8_t PORT2_DIS :1;
138 uint8_t : 5;
139 } bit; /*!< Structure used for bit access */
140 uint8_t reg; /*!< Type used for register access */
141} USB2422_PDB_Type;
142#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
143
144/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */
145#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
146typedef union {
147 struct {
148 uint8_t MAX_PWR_SP : 8;
149 } bit; /*!< Structure used for bit access */
150 uint8_t reg; /*!< Type used for register access */
151} USB2422_MAXPS_Type;
152#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
153
154/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */
155#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
156typedef union {
157 struct {
158 uint8_t MAX_PWR_BP : 8;
159 } bit; /*!< Structure used for bit access */
160 uint8_t reg; /*!< Type used for register access */
161} USB2422_MAXPB_Type;
162#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
163
164/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */
165#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
166typedef union {
167 struct {
168 uint8_t HC_MAX_C_SP : 8;
169 } bit; /*!< Structure used for bit access */
170 uint8_t reg; /*!< Type used for register access */
171} USB2422_HCMCS_Type;
172#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
173
174/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */
175#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
176typedef union {
177 struct {
178 uint8_t HC_MAX_C_BP : 8;
179 } bit; /*!< Structure used for bit access */
180 uint8_t reg; /*!< Type used for register access */
181} USB2422_HCMCB_Type;
182#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
183
184/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */
185#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
186typedef union {
187 struct {
188 uint8_t POWER_ON_TIME : 8;
189 } bit; /*!< Structure used for bit access */
190 uint8_t reg; /*!< Type used for register access */
191} USB2422_PWRT_Type;
192#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
193
194/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */
195#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
196typedef union {
197 struct {
198 uint8_t LANGID_LSB : 8;
199 } bit; /*!< Structure used for bit access */
200 uint8_t reg; /*!< Type used for register access */
201} USB2422_LANGID_LSB_Type;
202#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
203
204/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */
205#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
206typedef union {
207 struct {
208 uint8_t LANGID_MSB : 8;
209 } bit; /*!< Structure used for bit access */
210 uint8_t reg; /*!< Type used for register access */
211} USB2422_LANGID_MSB_Type;
212#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
213
214
215/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */
216#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
217typedef union {
218 struct {
219 uint8_t MFR_STR_LEN : 8;
220 } bit; /*!< Structure used for bit access */
221 uint8_t reg; /*!< Type used for register access */
222} USB2422_MFRSL_Type;
223#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
224
225/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */
226#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
227typedef union {
228 struct {
229 uint8_t PRD_STR_LEN : 8;
230 } bit; /*!< Structure used for bit access */
231 uint8_t reg; /*!< Type used for register access */
232} USB2422_PRDSL_Type;
233#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
234
235/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */
236#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
237typedef union {
238 struct {
239 uint8_t SER_STR_LEN : 8;
240 } bit; /*!< Structure used for bit access */
241 uint8_t reg; /*!< Type used for register access */
242} USB2422_SERSL_Type;
243#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
244
245/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */
246#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
247typedef uint16_t USB2422_MFRSTR_Type;
248#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
249
250/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */
251#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
252typedef uint16_t USB2422_PRDSTR_Type;
253#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
254
255/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */
256#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
257typedef uint16_t USB2422_SERSTR_Type;
258#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
259
260/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */
261#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
262typedef union {
263 struct {
264 uint8_t : 1;
265 uint8_t PORT1_BCE :1;
266 uint8_t PORT2_BCE :1;
267 uint8_t : 5;
268 } bit; /*!< Structure used for bit access */
269 uint8_t reg; /*!< Type used for register access */
270} USB2422_BCEN_Type;
271#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
272
273/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */
274#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
275typedef union {
276 struct {
277 uint8_t BOOST :2;
278 uint8_t : 6;
279 } bit; /*!< Structure used for bit access */
280 uint8_t reg; /*!< Type used for register access */
281} USB2422_BOOSTUP_Type;
282#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
283
284/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */
285#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
286typedef union {
287 struct {
288 uint8_t BOOST1 :2;
289 uint8_t BOOST2 :2;
290 uint8_t : 4;
291 } bit; /*!< Structure used for bit access */
292 uint8_t reg; /*!< Type used for register access */
293} USB2422_BOOSTDOWN_Type;
294#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
295
296/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */
297#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
298typedef union {
299 struct {
300 uint8_t : 1;
301 uint8_t PORT1_SP :1;
302 uint8_t PORT2_SP :1;
303 uint8_t : 5;
304 } bit; /*!< Structure used for bit access */
305 uint8_t reg; /*!< Type used for register access */
306} USB2422_PRTSP_Type;
307#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
308
309/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */
310#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
311typedef union {
312 struct {
313 uint8_t PORT1_REMAP: 4;
314 uint8_t PORT2_REMAP: 4;
315 } bit; /*!< Structure used for bit access */
316 uint8_t reg; /*!< Type used for register access */
317} USB2422_PRTR12_Type;
318#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
319#define USB2422_PRTR12_DISABLE 0
320#define USB2422_PRT12_P2TOL1 1
321#define USB2422_PRT12_P2XTOL2 2
322#define USB2422_PRT12_P1TOL1 1
323#define USB2422_PRT12_P1XTOL2 2
324
325/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */
326#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
327typedef union {
328 struct {
329 uint8_t USB_ATTACH: 1;
330 uint8_t RESET: 1;
331 uint8_t INTF_PWRDN: 1;
332 uint8_t : 5;
333 } bit; /*!< Structure used for bit access */
334 uint8_t reg; /*!< Type used for register access */
335} USB2422_STCD_Type;
336#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
337
338/** \brief USB2422 device hardware registers */
339#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
340typedef struct {
341 USB2422_VID_Type VID; /**< \brief Offset: 0x00*/
342 USB2422_PID_Type PID; /**< \brief Offset: 0x02*/
343 USB2422_DID_Type DID; /**< \brief Offset: 0x04*/
344 USB2422_CFG1_Type CFG1; /**< \brief Offset: 0x06*/
345 USB2422_CFG2_Type CFG2; /**< \brief Offset: 0x07*/
346 USB2422_CFG3_Type CFG3; /**< \brief Offset: 0x08*/
347 USB2422_NRD_Type NRD; /**< \brief Offset: 0x09*/
348 USB2422_PDS_Type PDS; /**< \brief Offset: 0x0A*/
349 USB2422_PDB_Type PDB; /**< \brief Offset: 0x0B*/
350 USB2422_MAXPS_Type MAXPS; /**< \brief Offset: 0x0C*/
351 USB2422_MAXPB_Type MAXPB; /**< \brief Offset: 0x0D*/
352 USB2422_HCMCS_Type HCMCS; /**< \brief Offset: 0x0E*/
353 USB2422_HCMCB_Type HCMCB; /**< \brief Offset: 0x0F*/
354 USB2422_PWRT_Type PWRT; /**< \brief Offset: 0x10*/
355 USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/
356 USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/
357 USB2422_MFRSL_Type MFRSL; /**< \brief Offset: 0x13*/
358 USB2422_PRDSL_Type PRDSL; /**< \brief Offset: 0x14*/
359 USB2422_SERSL_Type SERSL; /**< \brief Offset: 0x15*/
360 USB2422_MFRSTR_Type MFRSTR[31]; /**< \brief Offset: 0x16*/
361 USB2422_PRDSTR_Type PRDSTR[31]; /**< \brief Offset: 0x54*/
362 USB2422_SERSTR_Type SERSTR[31]; /**< \brief Offset: 0x92*/
363 USB2422_BCEN_Type BCEN; /**< \brief Offset: 0xD0*/
364 uint8_t Reserved1[0x25];
365 USB2422_BOOSTUP_Type BOOSTUP; /**< \brief Offset: 0xF6*/
366 uint8_t Reserved2[0x1];
367 USB2422_BOOSTDOWN_Type BOOSTDOWN; /**< \brief Offset: 0xF8*/
368 uint8_t Reserved3[0x1];
369 USB2422_PRTSP_Type PRTSP; /**< \brief Offset: 0xFA*/
370 USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/
371 uint8_t Reserved4[0x3];
372 USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/
373} Usb2422;
374#endif
375
376#define PORT_DETECT_RETRY_INTERVAL 2000
377
378#define USB_EXTRA_ADC_THRESHOLD 900
379
380#define USB_EXTRA_STATE_DISABLED 0
381#define USB_EXTRA_STATE_ENABLED 1
382#define USB_EXTRA_STATE_UNKNOWN 2
383#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
384
385#define USB_HOST_PORT_1 0
386#define USB_HOST_PORT_2 1
387#define USB_HOST_PORT_UNKNOWN 2
388
389extern uint8_t usb_host_port;
390extern uint8_t usb_extra_state;
391extern uint8_t usb_extra_manual;
392extern uint8_t usb_gcr_auto;
393
394void USB2422_init(void);
395void USB_reset(void);
396void USB_configure(void);
397uint16_t USB_active(void);
398void USB_set_host_by_voltage(void);
399uint16_t adc_get(uint8_t muxpos);
400uint8_t USB2422_Port_Detect_Init(void);
401void USB_HandleExtraDevice(void);
402void USB_ExtraSetState(uint8_t state);
403
404#endif //_USB2422_H_
405
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_atmel.h b/tmk_core/protocol/arm_atsam/usb/usb_atmel.h
new file mode 100644
index 000000000..7febdc9ec
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_atmel.h
@@ -0,0 +1,190 @@
1/**
2 * \file
3 *
4 * \brief All USB VIDs and PIDs from Atmel USB applications
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _USB_ATMEL_H_
48#define _USB_ATMEL_H_
49
50/**
51 * \defgroup usb_group USB Stack
52 *
53 * This stack includes the USB Device Stack, USB Host Stack and common
54 * definitions.
55 * @{
56 */
57
58//! @}
59
60/**
61 * \ingroup usb_group
62 * \defgroup usb_atmel_ids_group Atmel USB Identifiers
63 *
64 * This module defines Atmel PID and VIDs constants.
65 *
66 * @{
67 */
68
69//! \name Vendor Identifier assigned by USB org to ATMEL
70#define USB_VID_ATMEL 0x03EB
71
72//! \name Product Identifier assigned by ATMEL to AVR applications
73//! @{
74
75//! \name The range from 2000h to 20FFh is reserved to the old PID for C51, MEGA, and others.
76//! @{
77#define USB_PID_ATMEL_MEGA_HIDGENERIC 0x2013
78#define USB_PID_ATMEL_MEGA_HIDKEYBOARD 0x2017
79#define USB_PID_ATMEL_MEGA_CDC 0x2018
80#define USB_PID_ATMEL_MEGA_AUDIO_IN 0x2019
81#define USB_PID_ATMEL_MEGA_MS 0x201A
82#define USB_PID_ATMEL_MEGA_AUDIO_IN_OUT 0x201B
83#define USB_PID_ATMEL_MEGA_HIDMOUSE 0x201C
84#define USB_PID_ATMEL_MEGA_HIDMOUSE_CERTIF_U4 0x201D
85#define USB_PID_ATMEL_MEGA_CDC_MULTI 0x201E
86#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_USBKEY 0x2022
87#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_STK525 0x2023
88#define USB_PID_ATMEL_MEGA_MS_2 0x2029
89#define USB_PID_ATMEL_MEGA_MS_HIDMS 0x202A
90#define USB_PID_ATMEL_MEGA_MS_3 0x2032
91#define USB_PID_ATMEL_MEGA_LIBUSB 0x2050
92//! @}
93
94//! \name The range 2100h to 21FFh is reserved to PIDs for AVR Tools.
95//! @{
96#define USB_PID_ATMEL_XPLAINED 0x2122
97#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_2_4GHZ 0x214A
98#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_SUBGHZ 0x214B
99//! @}
100
101//! \name The range 2300h to 23FFh is reserved to PIDs for demo from ASF1.7=>
102//! @{
103#define USB_PID_ATMEL_UC3_ENUM 0x2300
104#define USB_PID_ATMEL_UC3_MS 0x2301
105#define USB_PID_ATMEL_UC3_MS_SDRAM_LOADER 0x2302
106#define USB_PID_ATMEL_UC3_EVK1100_CTRLPANEL 0x2303
107#define USB_PID_ATMEL_UC3_HID 0x2304
108#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID 0x2305
109#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID_MS 0x2306
110#define USB_PID_ATMEL_UC3_CDC 0x2307
111#define USB_PID_ATMEL_UC3_AUDIO_MICRO 0x2308
112#define USB_PID_ATMEL_UC3_CDC_DEBUG 0x2310 // Virtual Com (debug interface) on EVK11xx
113#define USB_PID_ATMEL_UC3_AUDIO_SPEAKER_MICRO 0x2311
114#define USB_PID_ATMEL_UC3_CDC_MSC 0x2312
115//! @}
116
117//! \name The range 2400h to 24FFh is reserved to PIDs for ASF applications
118//! @{
119#define USB_PID_ATMEL_ASF_HIDMOUSE 0x2400
120#define USB_PID_ATMEL_ASF_HIDKEYBOARD 0x2401
121#define USB_PID_ATMEL_ASF_HIDGENERIC 0x2402
122#define USB_PID_ATMEL_ASF_MSC 0x2403
123#define USB_PID_ATMEL_ASF_CDC 0x2404
124#define USB_PID_ATMEL_ASF_PHDC 0x2405
125#define USB_PID_ATMEL_ASF_HIDMTOUCH 0x2406
126#define USB_PID_ATMEL_ASF_MSC_HIDMOUSE 0x2420
127#define USB_PID_ATMEL_ASF_MSC_HIDS_CDC 0x2421
128#define USB_PID_ATMEL_ASF_MSC_HIDKEYBOARD 0x2422
129#define USB_PID_ATMEL_ASF_VENDOR_CLASS 0x2423
130#define USB_PID_ATMEL_ASF_MSC_CDC 0x2424
131#define USB_PID_ATMEL_ASF_TWO_CDC 0x2425
132#define USB_PID_ATMEL_ASF_SEVEN_CDC 0x2426
133#define USB_PID_ATMEL_ASF_XPLAIN_BC_POWERONLY 0x2430
134#define USB_PID_ATMEL_ASF_XPLAIN_BC_TERMINAL 0x2431
135#define USB_PID_ATMEL_ASF_XPLAIN_BC_TOUCH 0x2432
136#define USB_PID_ATMEL_ASF_AUDIO_SPEAKER 0x2433
137#define USB_PID_ATMEL_ASF_XMEGA_B1_XPLAINED 0x2434
138//! @}
139
140//! \name The range 2F00h to 2FFFh is reserved to official PIDs for AVR bootloaders
141//! Note, !!!! don't use this range for demos or examples !!!!
142//! @{
143#define USB_PID_ATMEL_DFU_ATXMEGA64C3 0x2FD6
144#define USB_PID_ATMEL_DFU_ATXMEGA128C3 0x2FD7
145#define USB_PID_ATMEL_DFU_ATXMEGA16C4 0x2FD8
146#define USB_PID_ATMEL_DFU_ATXMEGA32C4 0x2FD9
147#define USB_PID_ATMEL_DFU_ATXMEGA256C3 0x2FDA
148#define USB_PID_ATMEL_DFU_ATXMEGA384C3 0x2FDB
149#define USB_PID_ATMEL_DFU_ATUCL3_L4 0x2FDC
150#define USB_PID_ATMEL_DFU_ATXMEGA64A4U 0x2FDD
151#define USB_PID_ATMEL_DFU_ATXMEGA128A4U 0x2FDE
152
153#define USB_PID_ATMEL_DFU_ATXMEGA64B3 0x2FDF
154#define USB_PID_ATMEL_DFU_ATXMEGA128B3 0x2FE0
155#define USB_PID_ATMEL_DFU_ATXMEGA64B1 0x2FE1
156#define USB_PID_ATMEL_DFU_ATXMEGA256A3BU 0x2FE2
157#define USB_PID_ATMEL_DFU_ATXMEGA16A4U 0x2FE3
158#define USB_PID_ATMEL_DFU_ATXMEGA32A4U 0x2FE4
159#define USB_PID_ATMEL_DFU_ATXMEGA64A3U 0x2FE5
160#define USB_PID_ATMEL_DFU_ATXMEGA128A3U 0x2FE6
161#define USB_PID_ATMEL_DFU_ATXMEGA192A3U 0x2FE7
162#define USB_PID_ATMEL_DFU_ATXMEGA64A1U 0x2FE8
163#define USB_PID_ATMEL_DFU_ATUC3D 0x2FE9
164#define USB_PID_ATMEL_DFU_ATXMEGA128B1 0x2FEA
165#define USB_PID_ATMEL_DFU_AT32UC3C 0x2FEB
166#define USB_PID_ATMEL_DFU_ATXMEGA256A3U 0x2FEC
167#define USB_PID_ATMEL_DFU_ATXMEGA128A1U 0x2FED
168#define USB_PID_ATMEL_DFU_ATMEGA8U2 0x2FEE
169#define USB_PID_ATMEL_DFU_ATMEGA16U2 0x2FEF
170#define USB_PID_ATMEL_DFU_ATMEGA32U2 0x2FF0
171#define USB_PID_ATMEL_DFU_AT32UC3A3 0x2FF1
172#define USB_PID_ATMEL_DFU_ATMEGA32U6 0x2FF2
173#define USB_PID_ATMEL_DFU_ATMEGA16U4 0x2FF3
174#define USB_PID_ATMEL_DFU_ATMEGA32U4 0x2FF4
175#define USB_PID_ATMEL_DFU_AT32AP7200 0x2FF5
176#define USB_PID_ATMEL_DFU_AT32UC3B 0x2FF6
177#define USB_PID_ATMEL_DFU_AT90USB82 0x2FF7
178#define USB_PID_ATMEL_DFU_AT32UC3A 0x2FF8
179#define USB_PID_ATMEL_DFU_AT90USB64 0x2FF9
180#define USB_PID_ATMEL_DFU_AT90USB162 0x2FFA
181#define USB_PID_ATMEL_DFU_AT90USB128 0x2FFB
182// 2FFCh to 2FFFh used by C51 family products
183//! @}
184
185//! @}
186
187//! @}
188
189
190#endif // _USB_ATMEL_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_device_udd.c b/tmk_core/protocol/arm_atsam/usb/usb_device_udd.c
new file mode 100644
index 000000000..b31256df7
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_device_udd.c
@@ -0,0 +1,1097 @@
1/**
2 * \file
3 *
4 * \brief USB Device wrapper layer for compliance with common driver UDD
5 *
6 * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46#include "samd51j18a.h"
47#include <string.h>
48#include <stdlib.h>
49
50// Get USB device configuration
51#include "conf_usb.h"
52#include "udd.h"
53#include "usb.h"
54#include "status_codes.h"
55
56/**
57 * \ingroup usb_device_group
58 * \defgroup usb_device_udd_group USB Device Driver Implement (UDD)
59 * USB low-level driver for USB device mode
60 * @{
61 */
62// Check USB device configuration
63#ifdef USB_DEVICE_HS_SUPPORT
64# error The High speed mode is not supported on this part, please remove USB_DEVICE_HS_SUPPORT in conf_usb.h
65#endif
66
67//Note: This driver is adapted for SAMD51
68
69#ifndef UDC_REMOTEWAKEUP_LPM_ENABLE
70#define UDC_REMOTEWAKEUP_LPM_ENABLE()
71#endif
72#ifndef UDC_REMOTEWAKEUP_LPM_DISABLE
73#define UDC_REMOTEWAKEUP_LPM_DISABLE()
74#endif
75#ifndef UDC_SUSPEND_LPM_EVENT
76#define UDC_SUSPEND_LPM_EVENT()
77#endif
78
79/* for debug text */
80#ifdef USB_DEBUG
81# define dbg_print printf
82#else
83# define dbg_print(...)
84#endif
85
86/** Maximum size of a transfer in multi-packet mode */
87#define UDD_ENDPOINT_MAX_TRANS ((8*1024)-1)
88
89/** USB software device instance structure */
90struct usb_module usb_device;
91
92/**
93 * \name Clock management
94 *
95 * @{
96 */
97
98#define UDD_CLOCK_GEN 0
99
100static inline void udd_wait_clock_ready(void)
101{
102
103}
104
105/**
106 * \name Power management
107 *
108 * @{
109 */
110#define udd_sleep_mode(arg)
111/** @} */
112
113/**
114 * \name Control endpoint low level management routine.
115 *
116 * This function performs control endpoint management.
117 * It handles the SETUP/DATA/HANDSHAKE phases of a control transaction.
118 *
119 * @{
120 */
121
122/**
123 * \brief Buffer to store the data received on control endpoint (SETUP/OUT endpoint 0)
124 *
125 * Used to avoid a RAM buffer overflow in case of the payload buffer
126 * is smaller than control endpoint size
127 */
128UDC_BSS(4)
129uint8_t udd_ctrl_buffer[USB_DEVICE_EP_CTRL_SIZE];
130
131/** Bit definitions about endpoint control state machine for udd_ep_control_state */
132typedef enum {
133 UDD_EPCTRL_SETUP = 0, //!< Wait a SETUP packet
134 UDD_EPCTRL_DATA_OUT = 1, //!< Wait a OUT data packet
135 UDD_EPCTRL_DATA_IN = 2, //!< Wait a IN data packet
136 UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP = 3, //!< Wait a IN ZLP packet
137 UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP = 4, //!< Wait a OUT ZLP packet
138 UDD_EPCTRL_STALL_REQ = 5, //!< STALL enabled on IN & OUT packet
139} udd_ctrl_ep_state_t;
140
141/** Global variable to give and record information of the set up request management */
142udd_ctrl_request_t udd_g_ctrlreq;
143
144/** State of the endpoint control management */
145static udd_ctrl_ep_state_t udd_ep_control_state;
146
147/** Total number of data received/sent during data packet phase with previous payload buffers */
148static uint16_t udd_ctrl_prev_payload_nb_trans;
149
150/** Number of data received/sent to/from udd_g_ctrlreq.payload buffer */
151static uint16_t udd_ctrl_payload_nb_trans;
152
153/** @} */
154
155/**
156 * \name Management of bulk/interrupt/isochronous endpoints
157 *
158 * The UDD manages the data transfer on endpoints:
159 * - Start data transfer on endpoint with USB Device DMA
160 * - Send a ZLP packet if requested
161 * - Call callback registered to signal end of transfer
162 * The transfer abort and stall feature are supported.
163 *
164 * @{
165 */
166
167/**
168 * \brief Buffer to store the data received on bulk/interrupt endpoints
169 *
170 * Used to avoid a RAM buffer overflow in case of the user buffer
171 * is smaller than endpoint size
172 *
173 * \warning The protected interrupt endpoint size is 512 bytes maximum.
174 * \warning The isochronous and endpoint is not protected by this system and
175 * the user must always use a buffer corresponding at endpoint size.
176 */
177
178#if (defined USB_DEVICE_LOW_SPEED)
179UDC_BSS(4) uint8_t udd_ep_out_cache_buffer[USB_DEVICE_MAX_EP][8];
180#elif (defined USB_DEVICE_HS_SUPPORT)
181UDC_BSS(4) uint8_t udd_ep_out_cache_buffer[USB_DEVICE_MAX_EP][512];
182#else
183UDC_BSS(4) uint8_t udd_ep_out_cache_buffer[USB_DEVICE_MAX_EP][64];
184#endif
185
186/** Structure definition about job registered on an endpoint */
187typedef struct {
188 union {
189 //! Callback to call at the end of transfer
190 udd_callback_trans_t call_trans;
191 //! Callback to call when the endpoint halt is cleared
192 udd_callback_halt_cleared_t call_nohalt;
193 };
194 //! Buffer located in internal RAM to send or fill during job
195 uint8_t *buf;
196 //! Size of buffer to send or fill
197 iram_size_t buf_size;
198 //! Total number of data transferred on endpoint
199 iram_size_t nb_trans;
200 //! Endpoint size
201 uint16_t ep_size;
202 //! A job is registered on this endpoint
203 uint8_t busy:1;
204 //! A short packet is requested for this job on endpoint IN
205 uint8_t b_shortpacket:1;
206 //! The cache buffer is currently used on endpoint OUT
207 uint8_t b_use_out_cache_buffer:1;
208} udd_ep_job_t;
209
210/** Array to register a job on bulk/interrupt/isochronous endpoint */
211static udd_ep_job_t udd_ep_job[2 * USB_DEVICE_MAX_EP];
212
213/** @} */
214
215/**
216 * \brief Get the detailed job by endpoint number
217 * \param[in] ep Endpoint Address
218 * \retval pointer to an udd_ep_job_t structure instance
219 */
220static udd_ep_job_t* udd_ep_get_job(udd_ep_id_t ep)
221{
222 if ((ep == 0) || (ep == 0x80)) {
223 return NULL;
224 } else {
225 return &udd_ep_job[(2 * (ep & USB_EP_ADDR_MASK) + ((ep & USB_EP_DIR_IN) ? 1 : 0)) - 2];
226 }
227}
228
229/**
230 * \brief Endpoint IN process, continue to send packets or zero length packet
231 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
232 */
233static void udd_ep_trans_in_next(void* pointer)
234{
235 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
236 udd_ep_id_t ep = ep_callback_para->endpoint_address;
237 uint16_t ep_size, nb_trans;
238 uint16_t next_trans;
239 udd_ep_id_t ep_num;
240 udd_ep_job_t *ptr_job;
241
242 ptr_job = udd_ep_get_job(ep);
243 ep_num = ep & USB_EP_ADDR_MASK;
244
245 ep_size = ptr_job->ep_size;
246 /* Update number of data transferred */
247 nb_trans = ep_callback_para->sent_bytes;
248 ptr_job->nb_trans += nb_trans;
249
250 /* Need to send other data */
251 if (ptr_job->nb_trans != ptr_job->buf_size) {
252 next_trans = ptr_job->buf_size - ptr_job->nb_trans;
253 if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
254 /* The USB hardware support a maximum
255 * transfer size of UDD_ENDPOINT_MAX_TRANS Bytes */
256 next_trans = UDD_ENDPOINT_MAX_TRANS -(UDD_ENDPOINT_MAX_TRANS % ep_size);
257 }
258 /* Need ZLP, if requested and last packet is not a short packet */
259 ptr_job->b_shortpacket = ptr_job->b_shortpacket && (0 == (next_trans % ep_size));
260 usb_device_endpoint_write_buffer_job(&usb_device,ep_num,&ptr_job->buf[ptr_job->nb_trans],next_trans);
261 return;
262 }
263
264 /* Need to send a ZLP after all data transfer */
265 if (ptr_job->b_shortpacket) {
266 ptr_job->b_shortpacket = false;
267 /* Start new transfer */
268 usb_device_endpoint_write_buffer_job(&usb_device,ep_num,&ptr_job->buf[ptr_job->nb_trans],0);
269 return;
270 }
271
272 /* Job complete then call callback */
273 ptr_job->busy = false;
274 if (NULL != ptr_job->call_trans) {
275 ptr_job->call_trans(UDD_EP_TRANSFER_OK, ptr_job->nb_trans, ep);
276 }
277}
278
279/**
280 * \brief Endpoint OUT process, continue to receive packets or zero length packet
281 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
282 */
283static void udd_ep_trans_out_next(void* pointer)
284{
285 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
286 udd_ep_id_t ep = ep_callback_para->endpoint_address;
287 uint16_t ep_size, nb_trans;
288 uint16_t next_trans;
289 udd_ep_id_t ep_num;
290 udd_ep_job_t *ptr_job;
291
292 ptr_job = udd_ep_get_job(ep);
293 ep_num = ep & USB_EP_ADDR_MASK;
294
295 ep_size = ptr_job->ep_size;
296 /* Update number of data transferred */
297 nb_trans = ep_callback_para->received_bytes;
298
299 /* Can be necessary to copy data receive from cache buffer to user buffer */
300 if (ptr_job->b_use_out_cache_buffer) {
301 memcpy(&ptr_job->buf[ptr_job->nb_trans], udd_ep_out_cache_buffer[ep_num - 1], ptr_job->buf_size % ep_size);
302 }
303
304 /* Update number of data transferred */
305 ptr_job->nb_trans += nb_trans;
306 if (ptr_job->nb_trans > ptr_job->buf_size) {
307 ptr_job->nb_trans = ptr_job->buf_size;
308 }
309
310 /* If all previous data requested are received and user buffer not full
311 * then need to receive other data */
312 if ((nb_trans == ep_callback_para->out_buffer_size) && (ptr_job->nb_trans != ptr_job->buf_size)) {
313 next_trans = ptr_job->buf_size - ptr_job->nb_trans;
314 if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
315 /* The USB hardware support a maximum transfer size
316 * of UDD_ENDPOINT_MAX_TRANS Bytes */
317 next_trans = UDD_ENDPOINT_MAX_TRANS - (UDD_ENDPOINT_MAX_TRANS % ep_size);
318 } else {
319 next_trans -= next_trans % ep_size;
320 }
321
322 if (next_trans < ep_size) {
323 /* Use the cache buffer for Bulk or Interrupt size endpoint */
324 ptr_job->b_use_out_cache_buffer = true;
325 usb_device_endpoint_read_buffer_job(&usb_device,ep_num,udd_ep_out_cache_buffer[ep_num - 1],ep_size);
326 } else {
327 usb_device_endpoint_read_buffer_job(&usb_device,ep_num,&ptr_job->buf[ptr_job->nb_trans],next_trans);
328 }
329 return;
330 }
331
332 /* Job complete then call callback */
333 ptr_job->busy = false;
334 if (NULL != ptr_job->call_trans) {
335 ptr_job->call_trans(UDD_EP_TRANSFER_OK, ptr_job->nb_trans, ep);
336 }
337}
338
339/**
340 * \brief Endpoint Transfer Complete callback function, to do the next transfer depends on the direction(IN or OUT)
341 * \param[in] module_inst Pointer to USB module instance
342 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
343 */
344static void udd_ep_transfer_process(struct usb_module *module_inst, void* pointer)
345{
346 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
347 udd_ep_id_t ep = ep_callback_para->endpoint_address;
348
349 if (ep & USB_EP_DIR_IN) {
350 udd_ep_trans_in_next(pointer);
351 } else {
352 udd_ep_trans_out_next(pointer);
353 }
354}
355
356void udd_ep_abort(udd_ep_id_t ep)
357{
358 udd_ep_job_t *ptr_job;
359
360 usb_device_endpoint_abort_job(&usb_device, ep);
361
362 /* Job complete then call callback */
363 ptr_job = udd_ep_get_job(ep);
364 if (!ptr_job->busy) {
365 return;
366 }
367 ptr_job->busy = false;
368 if (NULL != ptr_job->call_trans) {
369 /* It can be a Transfer or stall callback */
370 ptr_job->call_trans(UDD_EP_TRANSFER_ABORT, ptr_job->nb_trans, ep);
371 }
372}
373
374bool udd_is_high_speed(void)
375{
376 return false;
377}
378
379uint16_t udd_get_frame_number(void)
380{
381 return usb_device_get_frame_number(&usb_device);
382}
383
384uint16_t udd_get_micro_frame_number(void)
385{
386 return usb_device_get_micro_frame_number(&usb_device);
387}
388
389void udd_ep_free(udd_ep_id_t ep)
390{
391 struct usb_device_endpoint_config config_ep;
392 usb_device_endpoint_get_config_defaults(&config_ep);
393
394 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
395 udd_ep_abort(ep);
396
397 config_ep.ep_address = ep;
398 config_ep.ep_type = USB_DEVICE_ENDPOINT_TYPE_DISABLE;
399 usb_device_endpoint_set_config(&usb_device, &config_ep);
400 usb_device_endpoint_unregister_callback(&usb_device,ep_num,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT);
401 usb_device_endpoint_disable_callback(&usb_device,ep,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT);
402}
403
404bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes, uint16_t MaxEndpointSize)
405{
406 struct usb_device_endpoint_config config_ep;
407 usb_device_endpoint_get_config_defaults(&config_ep);
408
409 config_ep.ep_address = ep;
410
411 if(MaxEndpointSize <= 8) {
412 config_ep.ep_size = USB_ENDPOINT_8_BYTE;
413 } else if(MaxEndpointSize <= 16) {
414 config_ep.ep_size = USB_ENDPOINT_16_BYTE;
415 } else if(MaxEndpointSize <= 32) {
416 config_ep.ep_size = USB_ENDPOINT_32_BYTE;
417 } else if(MaxEndpointSize <= 64) {
418 config_ep.ep_size = USB_ENDPOINT_64_BYTE;
419 } else if(MaxEndpointSize <= 128) {
420 config_ep.ep_size = USB_ENDPOINT_128_BYTE;
421 } else if(MaxEndpointSize <= 256) {
422 config_ep.ep_size = USB_ENDPOINT_256_BYTE;
423 } else if(MaxEndpointSize <= 512) {
424 config_ep.ep_size = USB_ENDPOINT_512_BYTE;
425 } else if(MaxEndpointSize <= 1023) {
426 config_ep.ep_size = USB_ENDPOINT_1023_BYTE;
427 } else {
428 return false;
429 }
430 udd_ep_job_t *ptr_job = udd_ep_get_job(ep);
431 ptr_job->ep_size = MaxEndpointSize;
432
433 bmAttributes = bmAttributes & USB_EP_TYPE_MASK;
434
435 /* Check endpoint type */
436 if(USB_EP_TYPE_ISOCHRONOUS == bmAttributes) {
437 config_ep.ep_type = USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS;
438 } else if (USB_EP_TYPE_BULK == bmAttributes) {
439 config_ep.ep_type = USB_DEVICE_ENDPOINT_TYPE_BULK;
440 } else if (USB_EP_TYPE_INTERRUPT == bmAttributes) {
441 config_ep.ep_type = USB_DEVICE_ENDPOINT_TYPE_INTERRUPT;
442 } else {
443 return false;
444 }
445
446 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
447
448 if (STATUS_OK != usb_device_endpoint_set_config(&usb_device, &config_ep)) {
449 return false;
450 }
451 usb_device_endpoint_register_callback(&usb_device,ep_num,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT,udd_ep_transfer_process);
452 usb_device_endpoint_enable_callback(&usb_device,ep,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT);
453 usb_device_endpoint_enable_callback(&usb_device,ep,USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL);
454
455 return true;
456}
457
458bool udd_ep_is_halted(udd_ep_id_t ep)
459{
460 return usb_device_endpoint_is_halted(&usb_device, ep);
461}
462
463bool udd_ep_set_halt(udd_ep_id_t ep)
464{
465 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
466
467 if (USB_DEVICE_MAX_EP < ep_num) {
468 return false;
469 }
470
471 usb_device_endpoint_set_halt(&usb_device, ep);
472
473 udd_ep_abort(ep);
474 return true;
475}
476
477bool udd_ep_clear_halt(udd_ep_id_t ep)
478{
479 udd_ep_job_t *ptr_job;
480 uint8_t ep_num = ep & USB_EP_ADDR_MASK;
481
482 if (USB_DEVICE_MAX_EP < ep_num) {
483 return false;
484 }
485 ptr_job = udd_ep_get_job(ep);
486
487 usb_device_endpoint_clear_halt(&usb_device, ep);
488
489 /* If a job is register on clear halt action then execute callback */
490 if (ptr_job->busy == true) {
491 ptr_job->busy = false;
492 ptr_job->call_nohalt();
493 }
494
495 return true;
496}
497
498bool udd_ep_wait_stall_clear(udd_ep_id_t ep, udd_callback_halt_cleared_t callback)
499{
500 udd_ep_id_t ep_num;
501 udd_ep_job_t *ptr_job;
502
503 ep_num = ep & USB_EP_ADDR_MASK;
504 if (USB_DEVICE_MAX_EP < ep_num) {
505 return false;
506 }
507
508 ptr_job = udd_ep_get_job(ep);
509 if (ptr_job->busy == true) {
510 return false; /* Job already on going */
511 }
512
513 /* Wait clear halt endpoint */
514 if (usb_device_endpoint_is_halted(&usb_device, ep)) {
515 /* Endpoint halted then registers the callback */
516 ptr_job->busy = true;
517 ptr_job->call_nohalt = callback;
518 return true;
519 } else if (usb_device_endpoint_is_configured(&usb_device, ep)) {
520 callback(); /* Endpoint not halted then call directly callback */
521 return true;
522 } else {
523 return false;
524 }
525}
526
527/**
528 * \brief Control Endpoint stall sending data
529 */
530static void udd_ctrl_stall_data(void)
531{
532 udd_ep_control_state = UDD_EPCTRL_STALL_REQ;
533
534 usb_device_endpoint_set_halt(&usb_device, USB_EP_DIR_IN);
535 usb_device_endpoint_clear_halt(&usb_device, USB_EP_DIR_OUT);
536}
537
538bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket, uint8_t *buf, iram_size_t buf_size, udd_callback_trans_t callback)
539{
540 udd_ep_id_t ep_num;
541 udd_ep_job_t *ptr_job;
542 uint32_t irqflags;
543
544 ep_num = ep & USB_EP_ADDR_MASK;
545
546 if ((USB_DEVICE_MAX_EP < ep_num) || (udd_ep_is_halted(ep))) {
547 return false;
548 }
549
550 ptr_job = udd_ep_get_job(ep);
551
552 irqflags = __get_PRIMASK();
553 __disable_irq();
554 __DMB();
555
556 if (ptr_job->busy == true) {
557 __DMB();
558 __set_PRIMASK(irqflags);
559 return false; /* Job already on going */
560 }
561
562 ptr_job->busy = true;
563 __DMB();
564 __set_PRIMASK(irqflags);
565
566 /* No job running, set up a new one */
567 ptr_job->buf = buf;
568 ptr_job->buf_size = buf_size;
569 ptr_job->nb_trans = 0;
570 ptr_job->call_trans = callback;
571 ptr_job->b_shortpacket = b_shortpacket;
572 ptr_job->b_use_out_cache_buffer = false;
573
574 /* Initialize value to simulate a empty transfer */
575 uint16_t next_trans;
576
577 if (ep & USB_EP_DIR_IN) {
578 if (0 != ptr_job->buf_size) {
579 next_trans = ptr_job->buf_size;
580 if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
581 next_trans = UDD_ENDPOINT_MAX_TRANS - (UDD_ENDPOINT_MAX_TRANS % ptr_job->ep_size);
582 }
583 ptr_job->b_shortpacket = ptr_job->b_shortpacket && (0 == (next_trans % ptr_job->ep_size));
584 } else if (true == ptr_job->b_shortpacket) {
585 ptr_job->b_shortpacket = false; /* avoid to send zero length packet again */
586 next_trans = 0;
587 } else {
588 ptr_job->busy = false;
589 if (NULL != ptr_job->call_trans) {
590 ptr_job->call_trans(UDD_EP_TRANSFER_OK, 0, ep);
591 }
592 return true;
593 }
594 return (STATUS_OK ==
595 usb_device_endpoint_write_buffer_job(&usb_device,
596 ep_num,&ptr_job->buf[0],next_trans));
597 } else {
598 if (0 != ptr_job->buf_size) {
599 next_trans = ptr_job->buf_size;
600 if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
601 /* The USB hardware support a maximum transfer size
602 * of UDD_ENDPOINT_MAX_TRANS Bytes */
603 next_trans = UDD_ENDPOINT_MAX_TRANS -
604 (UDD_ENDPOINT_MAX_TRANS % ptr_job->ep_size);
605 } else {
606 next_trans -= next_trans % ptr_job->ep_size;
607 }
608 if (next_trans < ptr_job->ep_size) {
609 ptr_job->b_use_out_cache_buffer = true;
610 return (STATUS_OK ==
611 usb_device_endpoint_read_buffer_job(&usb_device, ep_num,
612 udd_ep_out_cache_buffer[ep_num - 1],
613 ptr_job->ep_size));
614 } else {
615 return (STATUS_OK ==
616 usb_device_endpoint_read_buffer_job(&usb_device, ep_num,
617 &ptr_job->buf[0],next_trans));
618 }
619 } else {
620 ptr_job->busy = false;
621 if (NULL != ptr_job->call_trans) {
622 ptr_job->call_trans(UDD_EP_TRANSFER_OK, 0, ep);
623 }
624 return true;
625 }
626 }
627}
628
629void udd_set_address(uint8_t address)
630{
631 usb_device_set_address(&usb_device,address);
632}
633
634uint8_t udd_getaddress(void)
635{
636 return usb_device_get_address(&usb_device);
637}
638
639void udd_send_remotewakeup(void)
640{
641 uint32_t try = 5;
642 udd_wait_clock_ready();
643 udd_sleep_mode(UDD_STATE_IDLE);
644 while(2 != usb_get_state_machine_status(&usb_device) && try --) {
645 usb_device_send_remote_wake_up(&usb_device);
646 }
647}
648
649void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size )
650{
651 udd_g_ctrlreq.payload = payload;
652 udd_g_ctrlreq.payload_size = payload_size;
653}
654
655/**
656 * \brief Control Endpoint translate the data in buffer into Device Request Struct
657 */
658static void udd_ctrl_fetch_ram(void)
659{
660 udd_g_ctrlreq.req.bmRequestType = udd_ctrl_buffer[0];
661 udd_g_ctrlreq.req.bRequest = udd_ctrl_buffer[1];
662 udd_g_ctrlreq.req.wValue = ((uint16_t)(udd_ctrl_buffer[3]) << 8) + udd_ctrl_buffer[2];
663 udd_g_ctrlreq.req.wIndex = ((uint16_t)(udd_ctrl_buffer[5]) << 8) + udd_ctrl_buffer[4];
664 udd_g_ctrlreq.req.wLength = ((uint16_t)(udd_ctrl_buffer[7]) << 8) + udd_ctrl_buffer[6];
665}
666
667/**
668 * \brief Control Endpoint send out zero length packet
669 */
670static void udd_ctrl_send_zlp_in(void)
671{
672 udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP;
673 usb_device_endpoint_setup_buffer_job(&usb_device,udd_ctrl_buffer);
674 usb_device_endpoint_write_buffer_job(&usb_device,0,udd_g_ctrlreq.payload,0);
675}
676
677/**
678 * \brief Process control endpoint IN transaction
679 */
680static void udd_ctrl_in_sent(void)
681{
682 static bool b_shortpacket = false;
683 uint16_t nb_remain;
684
685 nb_remain = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans;
686
687 if (0 == nb_remain) {
688 /* All content of current buffer payload are sent Update number of total data sending by previous payload buffer */
689 udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans;
690 if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_nb_trans) || b_shortpacket) {
691 /* All data requested are transferred or a short packet has been sent, then it is the end of data phase.
692 * Generate an OUT ZLP for handshake phase */
693 udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP;
694 usb_device_endpoint_setup_buffer_job(&usb_device,udd_ctrl_buffer);
695 return;
696 }
697 /* Need of new buffer because the data phase is not complete */
698 if ((!udd_g_ctrlreq.over_under_run) || (!udd_g_ctrlreq.over_under_run())) {
699 /* Under run then send zlp on IN
700 * Here nb_remain=0, this allows to send a IN ZLP */
701 } else {
702 /* A new payload buffer is given */
703 udd_ctrl_payload_nb_trans = 0;
704 nb_remain = udd_g_ctrlreq.payload_size;
705 }
706 }
707
708 /* Continue transfer and send next data */
709 if (nb_remain >= USB_DEVICE_EP_CTRL_SIZE) {
710 nb_remain = USB_DEVICE_EP_CTRL_SIZE;
711 b_shortpacket = false;
712 } else {
713 b_shortpacket = true;
714 }
715
716 /* Link payload buffer directly on USB hardware */
717 usb_device_endpoint_write_buffer_job(&usb_device,0,udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans,nb_remain);
718
719 udd_ctrl_payload_nb_trans += nb_remain;
720}
721
722/**
723 * \brief Process control endpoint OUT transaction
724 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
725 */
726static void udd_ctrl_out_received(void* pointer)
727{
728 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
729
730 uint16_t nb_data;
731 nb_data = ep_callback_para->received_bytes; /* Read data received during OUT phase */
732
733 if (udd_g_ctrlreq.payload_size < (udd_ctrl_payload_nb_trans + nb_data)) {
734 /* Payload buffer too small */
735 nb_data = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans;
736 }
737
738 memcpy((uint8_t *) (udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans), udd_ctrl_buffer, nb_data);
739 udd_ctrl_payload_nb_trans += nb_data;
740
741 if ((USB_DEVICE_EP_CTRL_SIZE != nb_data) || \
742 (udd_g_ctrlreq.req.wLength <= (udd_ctrl_prev_payload_nb_trans + udd_ctrl_payload_nb_trans))) {
743 /* End of reception because it is a short packet
744 * or all data are transferred */
745
746 /* Before send ZLP, call intermediate callback
747 * in case of data receive generate a stall */
748 udd_g_ctrlreq.payload_size = udd_ctrl_payload_nb_trans;
749 if (NULL != udd_g_ctrlreq.over_under_run) {
750 if (!udd_g_ctrlreq.over_under_run()) {
751 /* Stall ZLP */
752 udd_ep_control_state = UDD_EPCTRL_STALL_REQ;
753 /* Stall all packets on IN & OUT control endpoint */
754 udd_ep_set_halt(0);
755 /* Ack reception of OUT to replace NAK by a STALL */
756 return;
757 }
758 }
759 /* Send IN ZLP to ACK setup request */
760 udd_ctrl_send_zlp_in();
761 return;
762 }
763
764 if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_nb_trans) {
765 /* Overrun then request a new payload buffer */
766 if (!udd_g_ctrlreq.over_under_run) {
767 /* No callback available to request a new payload buffer
768 * Stall ZLP */
769 udd_ep_control_state = UDD_EPCTRL_STALL_REQ;
770 /* Stall all packets on IN & OUT control endpoint */
771 udd_ep_set_halt(0);
772 return;
773 }
774 if (!udd_g_ctrlreq.over_under_run()) {
775 /* No new payload buffer delivered
776 * Stall ZLP */
777 udd_ep_control_state = UDD_EPCTRL_STALL_REQ;
778 /* Stall all packets on IN & OUT control endpoint */
779 udd_ep_set_halt(0);
780 return;
781 }
782 /* New payload buffer available
783 * Update number of total data received */
784 udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans;
785
786 /* Reinitialize reception on payload buffer */
787 udd_ctrl_payload_nb_trans = 0;
788 }
789 usb_device_endpoint_read_buffer_job(&usb_device,0,udd_ctrl_buffer,USB_DEVICE_EP_CTRL_SIZE);
790}
791
792/**
793 * \internal
794 * \brief Endpoint 0 (control) SETUP received callback
795 * \param[in] module_inst pointer to USB module instance
796 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
797 */
798static void _usb_ep0_on_setup(struct usb_module *module_inst, void* pointer)
799{
800 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
801
802 if (UDD_EPCTRL_SETUP != udd_ep_control_state) {
803 if (NULL != udd_g_ctrlreq.callback) {
804 udd_g_ctrlreq.callback();
805 }
806 udd_ep_control_state = UDD_EPCTRL_SETUP;
807 }
808 if ( 8 != ep_callback_para->received_bytes) {
809 udd_ctrl_stall_data();
810 return;
811 } else {
812 udd_ctrl_fetch_ram();
813 if (false == udc_process_setup()) {
814 udd_ctrl_stall_data();
815 return;
816 } else if (Udd_setup_is_in()) {
817 udd_ctrl_prev_payload_nb_trans = 0;
818 udd_ctrl_payload_nb_trans = 0;
819 udd_ep_control_state = UDD_EPCTRL_DATA_IN;
820 usb_device_endpoint_read_buffer_job(&usb_device,0,udd_ctrl_buffer,USB_DEVICE_EP_CTRL_SIZE);
821 udd_ctrl_in_sent();
822 } else {
823 if(0 == udd_g_ctrlreq.req.wLength) {
824 udd_ctrl_send_zlp_in();
825 return;
826 } else {
827 udd_ctrl_prev_payload_nb_trans = 0;
828 udd_ctrl_payload_nb_trans = 0;
829 udd_ep_control_state = UDD_EPCTRL_DATA_OUT;
830 /* Initialize buffer size and enable OUT bank */
831 usb_device_endpoint_read_buffer_job(&usb_device,0,udd_ctrl_buffer,USB_DEVICE_EP_CTRL_SIZE);
832 }
833 }
834 }
835}
836
837/**
838 * \brief Control Endpoint Process when underflow condition has occurred
839 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
840 */
841static void udd_ctrl_underflow(void* pointer)
842{
843 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
844
845 if (UDD_EPCTRL_DATA_OUT == udd_ep_control_state) {
846 /* Host want to stop OUT transaction
847 * then stop to wait OUT data phase and wait IN ZLP handshake */
848 udd_ctrl_send_zlp_in();
849 } else if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) {
850 /* A OUT handshake is waiting by device,
851 * but host want extra IN data then stall extra IN data */
852 usb_device_endpoint_set_halt(&usb_device, ep_callback_para->endpoint_address);
853 }
854}
855
856/**
857 * \brief Control Endpoint Process when overflow condition has occurred
858 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
859 */
860static void udd_ctrl_overflow(void* pointer)
861{
862 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
863
864 if (UDD_EPCTRL_DATA_IN == udd_ep_control_state) {
865 /* Host want to stop IN transaction
866 * then stop to wait IN data phase and wait OUT ZLP handshake */
867 udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP;
868 } else if (UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) {
869 /* A IN handshake is waiting by device,
870 * but host want extra OUT data then stall extra OUT data and following status stage */
871 usb_device_endpoint_set_halt(&usb_device, ep_callback_para->endpoint_address);
872 }
873}
874
875/**
876 * \internal
877 * \brief Control endpoint transfer fail callback function
878 * \param[in] module_inst Pointer to USB module instance
879 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
880 */
881static void _usb_ep0_on_tansfer_fail(struct usb_module *module_inst, void* pointer)
882{
883 struct usb_endpoint_callback_parameter *ep_callback_para = (struct usb_endpoint_callback_parameter*)pointer;
884
885 if(ep_callback_para->endpoint_address & USB_EP_DIR_IN) {
886 udd_ctrl_underflow(pointer);
887 } else {
888 udd_ctrl_overflow(pointer);
889 }
890}
891
892/**
893 * \internal
894 * \brief Control endpoint transfer complete callback function
895 * \param[in] module_inst Pointer to USB module instance
896 * \param[in] pointer Pointer to the endpoint transfer status parameter struct from driver layer.
897 */
898static void _usb_ep0_on_tansfer_ok(struct usb_module *module_inst, void *pointer)
899{
900 if (UDD_EPCTRL_DATA_OUT == udd_ep_control_state) { /* handshake Out for status stage */
901 udd_ctrl_out_received(pointer);
902 } else if (UDD_EPCTRL_DATA_IN == udd_ep_control_state) { /* handshake In for status stage */
903 udd_ctrl_in_sent();
904 } else {
905 if (NULL != udd_g_ctrlreq.callback) {
906 udd_g_ctrlreq.callback();
907 }
908 udd_ep_control_state = UDD_EPCTRL_SETUP;
909 }
910}
911
912/**
913 * \brief Enable Control Endpoint
914 * \param[in] module_inst Pointer to USB module instance
915 */
916static void udd_ctrl_ep_enable(struct usb_module *module_inst)
917{
918 /* USB Device Endpoint0 Configuration */
919 struct usb_device_endpoint_config config_ep0;
920
921 usb_device_endpoint_get_config_defaults(&config_ep0);
922 config_ep0.ep_size = (enum usb_endpoint_size)(32 - clz(((uint32_t)Min(Max(USB_DEVICE_EP_CTRL_SIZE, 8), 1024) << 1) - 1) - 1 - 3);
923 usb_device_endpoint_set_config(module_inst,&config_ep0);
924
925 usb_device_endpoint_setup_buffer_job(module_inst,udd_ctrl_buffer);
926
927 usb_device_endpoint_register_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_RXSTP, _usb_ep0_on_setup );
928 usb_device_endpoint_register_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT,_usb_ep0_on_tansfer_ok );
929 usb_device_endpoint_register_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL,_usb_ep0_on_tansfer_fail );
930 usb_device_endpoint_enable_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_RXSTP);
931 usb_device_endpoint_enable_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_TRCPT);
932 usb_device_endpoint_enable_callback(module_inst,0,USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL);
933
934#ifdef USB_DEVICE_LPM_SUPPORT
935 // Enable LPM feature
936 usb_device_set_lpm_mode(module_inst, USB_DEVICE_LPM_ACK);
937#endif
938
939 udd_ep_control_state = UDD_EPCTRL_SETUP;
940}
941
942/**
943 * \internal
944 * \brief Control endpoint Suspend callback function
945 * \param[in] module_inst Pointer to USB module instance
946 * \param[in] pointer Pointer to the callback parameter from driver layer.
947 */
948static void _usb_on_suspend(struct usb_module *module_inst, void *pointer)
949{
950 usb_device_disable_callback(&usb_device, USB_DEVICE_CALLBACK_SUSPEND);
951 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_WAKEUP);
952 udd_sleep_mode(UDD_STATE_SUSPEND);
953#ifdef UDC_SUSPEND_EVENT
954 UDC_SUSPEND_EVENT();
955#endif
956}
957
958#ifdef USB_DEVICE_LPM_SUPPORT
959static void _usb_device_lpm_suspend(struct usb_module *module_inst, void *pointer)
960{
961 dbg_print("LPM_SUSP\n");
962
963 uint32_t *lpm_wakeup_enable;
964 lpm_wakeup_enable = (uint32_t *)pointer;
965
966 usb_device_disable_callback(&usb_device, USB_DEVICE_CALLBACK_LPMSUSP);
967 usb_device_disable_callback(&usb_device, USB_DEVICE_CALLBACK_SUSPEND);
968 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_WAKEUP);
969
970//#warning Here the sleep mode must be choose to have a DFLL startup time < bmAttribut.HIRD
971 udd_sleep_mode(UDD_STATE_SUSPEND_LPM); // Enter in LPM SUSPEND mode
972 if ((*lpm_wakeup_enable)) {
973 UDC_REMOTEWAKEUP_LPM_ENABLE();
974 }
975 if (!(*lpm_wakeup_enable)) {
976 UDC_REMOTEWAKEUP_LPM_DISABLE();
977 }
978 UDC_SUSPEND_LPM_EVENT();
979}
980#endif
981
982/**
983 * \internal
984 * \brief Control endpoint SOF callback function
985 * \param[in] module_inst Pointer to USB module instance
986 * \param[in] pointer Pointer to the callback parameter from driver layer.
987 */
988static void _usb_on_sof_notify(struct usb_module *module_inst, void *pointer)
989{
990 udc_sof_notify();
991#ifdef UDC_SOF_EVENT
992 UDC_SOF_EVENT();
993#endif
994}
995
996/**
997 * \internal
998 * \brief Control endpoint Reset callback function
999 * \param[in] module_inst Pointer to USB module instance
1000 * \param[in] pointer Pointer to the callback parameter from driver layer.
1001 */
1002static void _usb_on_bus_reset(struct usb_module *module_inst, void *pointer)
1003{
1004 // Reset USB Device Stack Core
1005 udc_reset();
1006 usb_device_set_address(module_inst,0);
1007 udd_ctrl_ep_enable(module_inst);
1008}
1009
1010/**
1011 * \internal
1012 * \brief Control endpoint Wakeup callback function
1013 * \param[in] module_inst Pointer to USB module instance
1014 * \param[in] pointer Pointer to the callback parameter from driver layer.
1015 */
1016static void _usb_on_wakeup(struct usb_module *module_inst, void *pointer)
1017{
1018 udd_wait_clock_ready();
1019
1020 usb_device_disable_callback(&usb_device, USB_DEVICE_CALLBACK_WAKEUP);
1021 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_SUSPEND);
1022#ifdef USB_DEVICE_LPM_SUPPORT
1023 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_LPMSUSP, _usb_device_lpm_suspend);
1024 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_LPMSUSP);
1025#endif
1026 udd_sleep_mode(UDD_STATE_IDLE);
1027#ifdef UDC_RESUME_EVENT
1028 UDC_RESUME_EVENT();
1029#endif
1030}
1031
1032void udd_detach(void)
1033{
1034 usb_device_detach(&usb_device);
1035 udd_sleep_mode(UDD_STATE_SUSPEND);
1036}
1037
1038void udd_attach(void)
1039{
1040 udd_sleep_mode(UDD_STATE_IDLE);
1041 usb_device_attach(&usb_device);
1042
1043 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_SUSPEND, _usb_on_suspend);
1044 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_SOF, _usb_on_sof_notify);
1045 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_RESET, _usb_on_bus_reset);
1046 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_WAKEUP, _usb_on_wakeup);
1047
1048 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_SUSPEND);
1049 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_SOF);
1050 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_RESET);
1051 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_WAKEUP);
1052#ifdef USB_DEVICE_LPM_SUPPORT
1053 usb_device_register_callback(&usb_device, USB_DEVICE_CALLBACK_LPMSUSP, _usb_device_lpm_suspend);
1054 usb_device_enable_callback(&usb_device, USB_DEVICE_CALLBACK_LPMSUSP);
1055#endif
1056}
1057
1058void udd_enable(void)
1059{
1060 uint32_t irqflags;
1061
1062 /* To avoid USB interrupt before end of initialization */
1063 irqflags = __get_PRIMASK();
1064 __disable_irq();
1065 __DMB();
1066
1067 struct usb_config config_usb;
1068
1069 /* USB Module configuration */
1070 usb_get_config_defaults(&config_usb);
1071 config_usb.source_generator = UDD_CLOCK_GEN;
1072 usb_init(&usb_device, USB, &config_usb);
1073
1074 /* USB Module Enable */
1075 usb_enable(&usb_device);
1076
1077 /* Check clock after enable module, request the clock */
1078 udd_wait_clock_ready();
1079
1080 udd_sleep_mode(UDD_STATE_SUSPEND);
1081
1082 // No VBus detect, assume always high
1083#ifndef USB_DEVICE_ATTACH_AUTO_DISABLE
1084 udd_attach();
1085#endif
1086
1087 __DMB();
1088 __set_PRIMASK(irqflags);
1089}
1090
1091void udd_disable(void)
1092{
1093 udd_detach();
1094
1095 udd_sleep_mode(UDD_STATE_OFF);
1096}
1097/** @} */
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_main.h b/tmk_core/protocol/arm_atsam/usb/usb_main.h
new file mode 100644
index 000000000..b7adaa1a7
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_main.h
@@ -0,0 +1,97 @@
1/**
2 * \file
3 *
4 * \brief Declaration of main function used by HID keyboard example
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _MAIN_H_
48#define _MAIN_H_
49
50//Enters the application in low power mode
51//Callback called when USB host sets USB line in suspend state
52void main_suspend_action(void);
53
54//Called by UDD when the USB line exit of suspend state
55void main_resume_action(void);
56
57//Called when a start of frame is received on USB line
58void main_sof_action(void);
59
60//Called by UDC when USB Host request to enable remote wakeup
61void main_remotewakeup_enable(void);
62
63//Called by UDC when USB Host request to disable remote wakeup
64void main_remotewakeup_disable(void);
65
66
67#ifdef KBD
68extern volatile bool main_b_kbd_enable;
69bool main_kbd_enable(void);
70void main_kbd_disable(void);
71#endif //KBD
72
73#ifdef NKRO
74extern volatile bool main_b_nkro_enable;
75bool main_nkro_enable(void);
76void main_nkro_disable(void);
77#endif //NKRO
78
79#ifdef EXK
80extern volatile bool main_b_exk_enable;
81bool main_exk_enable(void);
82void main_exk_disable(void);
83#endif //EXK
84
85#ifdef MOU
86extern volatile bool main_b_mou_enable;
87bool main_mou_enable(void);
88void main_mou_disable(void);
89#endif //MOU
90
91#ifdef RAW
92extern volatile bool main_b_raw_enable;
93bool main_raw_enable(void);
94void main_raw_disable(void);
95#endif //RAW
96
97#endif // _MAIN_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_protocol.h b/tmk_core/protocol/arm_atsam/usb/usb_protocol.h
new file mode 100644
index 000000000..892a7d3a5
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_protocol.h
@@ -0,0 +1,498 @@
1/**
2 * \file
3 *
4 * \brief USB protocol definitions.
5 *
6 * This file contains the USB definitions and data structures provided by the
7 * USB 2.0 specification.
8 *
9 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
10 *
11 * \asf_license_start
12 *
13 * \page License
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright notice,
19 * this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 *
25 * 3. The name of Atmel may not be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * 4. This software may only be redistributed and used in connection with an
29 * Atmel microcontroller product.
30 *
31 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
34 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
35 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
42 *
43 * \asf_license_stop
44 *
45 */
46/*
47 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
48 */
49
50#ifndef _USB_PROTOCOL_H_
51#define _USB_PROTOCOL_H_
52
53#include "usb_atmel.h"
54
55/**
56 * \ingroup usb_group
57 * \defgroup usb_protocol_group USB Protocol Definitions
58 *
59 * This module defines constants and data structures provided by the USB
60 * 2.0 specification.
61 *
62 * @{
63 */
64
65//! Value for field bcdUSB
66#define USB_V2_0 0x0200 //!< USB Specification version 2.00
67#define USB_V2_1 0x0201 //!< USB Specification version 2.01
68
69/*! \name Generic definitions (Class, subclass and protocol)
70 */
71//! @{
72#define NO_CLASS 0x00
73#define CLASS_VENDOR_SPECIFIC 0xFF
74#define NO_SUBCLASS 0x00
75#define NO_PROTOCOL 0x00
76//! @}
77
78//! \name IAD (Interface Association Descriptor) constants
79//! @{
80#define CLASS_IAD 0xEF
81#define SUB_CLASS_IAD 0x02
82#define PROTOCOL_IAD 0x01
83//! @}
84
85/**
86 * \brief USB request data transfer direction (bmRequestType)
87 */
88#define USB_REQ_DIR_OUT (0<<7) //!< Host to device
89#define USB_REQ_DIR_IN (1<<7) //!< Device to host
90#define USB_REQ_DIR_MASK (1<<7) //!< Mask
91
92/**
93 * \brief USB request types (bmRequestType)
94 */
95#define USB_REQ_TYPE_STANDARD (0<<5) //!< Standard request
96#define USB_REQ_TYPE_CLASS (1<<5) //!< Class-specific request
97#define USB_REQ_TYPE_VENDOR (2<<5) //!< Vendor-specific request
98#define USB_REQ_TYPE_MASK (3<<5) //!< Mask
99
100/**
101 * \brief USB recipient codes (bmRequestType)
102 */
103#define USB_REQ_RECIP_DEVICE (0<<0) //!< Recipient device
104#define USB_REQ_RECIP_INTERFACE (1<<0) //!< Recipient interface
105#define USB_REQ_RECIP_ENDPOINT (2<<0) //!< Recipient endpoint
106#define USB_REQ_RECIP_OTHER (3<<0) //!< Recipient other
107#define USB_REQ_RECIP_MASK (0x1F) //!< Mask
108
109/**
110 * \brief Standard USB requests (bRequest)
111 */
112enum usb_reqid {
113 USB_REQ_GET_STATUS = 0,
114 USB_REQ_CLEAR_FEATURE = 1,
115 USB_REQ_SET_FEATURE = 3,
116 USB_REQ_SET_ADDRESS = 5,
117 USB_REQ_GET_DESCRIPTOR = 6,
118 USB_REQ_SET_DESCRIPTOR = 7,
119 USB_REQ_GET_CONFIGURATION = 8,
120 USB_REQ_SET_CONFIGURATION = 9,
121 USB_REQ_GET_INTERFACE = 10,
122 USB_REQ_SET_INTERFACE = 11,
123 USB_REQ_SYNCH_FRAME = 12,
124};
125
126/**
127 * \brief Standard USB device status flags
128 *
129 */
130enum usb_device_status {
131 USB_DEV_STATUS_BUS_POWERED = 0,
132 USB_DEV_STATUS_SELF_POWERED = 1,
133 USB_DEV_STATUS_REMOTEWAKEUP = 2
134};
135
136/**
137 * \brief Standard USB Interface status flags
138 *
139 */
140enum usb_interface_status {
141 USB_IFACE_STATUS_RESERVED = 0
142};
143
144/**
145 * \brief Standard USB endpoint status flags
146 *
147 */
148enum usb_endpoint_status {
149 USB_EP_STATUS_HALTED = 1,
150};
151
152/**
153 * \brief Standard USB device feature flags
154 *
155 * \note valid for SetFeature request.
156 */
157enum usb_device_feature {
158 USB_DEV_FEATURE_REMOTE_WAKEUP = 1, //!< Remote wakeup enabled
159 USB_DEV_FEATURE_TEST_MODE = 2, //!< USB test mode
160 USB_DEV_FEATURE_OTG_B_HNP_ENABLE = 3,
161 USB_DEV_FEATURE_OTG_A_HNP_SUPPORT = 4,
162 USB_DEV_FEATURE_OTG_A_ALT_HNP_SUPPORT = 5
163};
164
165/**
166 * \brief Test Mode possible on HS USB device
167 *
168 * \note valid for USB_DEV_FEATURE_TEST_MODE request.
169 */
170enum usb_device_hs_test_mode {
171 USB_DEV_TEST_MODE_J = 1,
172 USB_DEV_TEST_MODE_K = 2,
173 USB_DEV_TEST_MODE_SE0_NAK = 3,
174 USB_DEV_TEST_MODE_PACKET = 4,
175 USB_DEV_TEST_MODE_FORCE_ENABLE = 5,
176};
177
178/**
179 * \brief Standard USB endpoint feature/status flags
180 */
181enum usb_endpoint_feature {
182 USB_EP_FEATURE_HALT = 0,
183};
184
185/**
186 * \brief Standard USB Test Mode Selectors
187 */
188enum usb_test_mode_selector {
189 USB_TEST_J = 0x01,
190 USB_TEST_K = 0x02,
191 USB_TEST_SE0_NAK = 0x03,
192 USB_TEST_PACKET = 0x04,
193 USB_TEST_FORCE_ENABLE = 0x05,
194};
195
196/**
197 * \brief Standard USB descriptor types
198 */
199enum usb_descriptor_type {
200 USB_DT_DEVICE = 1,
201 USB_DT_CONFIGURATION = 2,
202 USB_DT_STRING = 3,
203 USB_DT_INTERFACE = 4,
204 USB_DT_ENDPOINT = 5,
205 USB_DT_DEVICE_QUALIFIER = 6,
206 USB_DT_OTHER_SPEED_CONFIGURATION = 7,
207 USB_DT_INTERFACE_POWER = 8,
208 USB_DT_OTG = 9,
209 USB_DT_IAD = 0x0B,
210 USB_DT_BOS = 0x0F,
211 USB_DT_DEVICE_CAPABILITY = 0x10,
212};
213
214/**
215 * \brief USB Device Capability types
216 */
217enum usb_capability_type {
218 USB_DC_USB20_EXTENSION = 0x02,
219};
220
221/**
222 * \brief USB Device Capability - USB 2.0 Extension
223 * To fill bmAttributes field of usb_capa_ext_desc_t structure.
224 */
225enum usb_capability_extension_attr {
226 USB_DC_EXT_LPM = 0x00000002,
227};
228
229#define HIRD_50_US 0
230#define HIRD_125_US 1
231#define HIRD_200_US 2
232#define HIRD_275_US 3
233#define HIRD_350_US 4
234#define HIRD_425_US 5
235#define HIRD_500_US 6
236#define HIRD_575_US 7
237#define HIRD_650_US 8
238#define HIRD_725_US 9
239#define HIRD_800_US 10
240#define HIRD_875_US 11
241#define HIRD_950_US 12
242#define HIRD_1025_US 13
243#define HIRD_1100_US 14
244#define HIRD_1175_US 15
245
246/** Fields definition from a LPM TOKEN */
247#define USB_LPM_ATTRIBUT_BLINKSTATE_MASK (0xF << 0)
248#define USB_LPM_ATTRIBUT_FIRD_MASK (0xF << 4)
249#define USB_LPM_ATTRIBUT_REMOTEWAKE_MASK (1 << 8)
250#define USB_LPM_ATTRIBUT_BLINKSTATE(value) ((value & 0xF) << 0)
251#define USB_LPM_ATTRIBUT_FIRD(value) ((value & 0xF) << 4)
252#define USB_LPM_ATTRIBUT_REMOTEWAKE(value) ((value & 1) << 8)
253#define USB_LPM_ATTRIBUT_BLINKSTATE_L1 USB_LPM_ATTRIBUT_BLINKSTATE(1)
254
255/**
256 * \brief Standard USB endpoint transfer types
257 */
258enum usb_ep_type {
259 USB_EP_TYPE_CONTROL = 0x00,
260 USB_EP_TYPE_ISOCHRONOUS = 0x01,
261 USB_EP_TYPE_BULK = 0x02,
262 USB_EP_TYPE_INTERRUPT = 0x03,
263 USB_EP_TYPE_MASK = 0x03,
264};
265
266/**
267 * \brief Standard USB language IDs for string descriptors
268 */
269enum usb_langid {
270 USB_LANGID_EN_US = 0x0409, //!< English (United States)
271};
272
273/**
274 * \brief Mask selecting the index part of an endpoint address
275 */
276#define USB_EP_ADDR_MASK 0x0f
277
278//! \brief USB address identifier
279typedef uint8_t usb_add_t;
280
281/**
282 * \brief Endpoint transfer direction is IN
283 */
284#define USB_EP_DIR_IN 0x80
285
286/**
287 * \brief Endpoint transfer direction is OUT
288 */
289#define USB_EP_DIR_OUT 0x00
290
291//! \brief Endpoint identifier
292typedef uint8_t usb_ep_t;
293
294/**
295 * \brief Maximum length in bytes of a USB descriptor
296 *
297 * The maximum length of a USB descriptor is limited by the 8-bit
298 * bLength field.
299 */
300#define USB_MAX_DESC_LEN 255
301
302/*
303 * 2-byte alignment requested for all USB structures.
304 */
305COMPILER_PACK_SET(1)
306
307/**
308 * \brief A USB Device SETUP request
309 *
310 * The data payload of SETUP packets always follows this structure.
311 */
312typedef struct {
313 uint8_t bmRequestType;
314 uint8_t bRequest;
315 le16_t wValue;
316 le16_t wIndex;
317 le16_t wLength;
318} usb_setup_req_t;
319
320/**
321 * \brief Standard USB device descriptor structure
322 */
323typedef struct {
324 uint8_t bLength;
325 uint8_t bDescriptorType;
326 le16_t bcdUSB;
327 uint8_t bDeviceClass;
328 uint8_t bDeviceSubClass;
329 uint8_t bDeviceProtocol;
330 uint8_t bMaxPacketSize0;
331 le16_t idVendor;
332 le16_t idProduct;
333 le16_t bcdDevice;
334 uint8_t iManufacturer;
335 uint8_t iProduct;
336 uint8_t iSerialNumber;
337 uint8_t bNumConfigurations;
338} usb_dev_desc_t;
339
340/**
341 * \brief Standard USB device qualifier descriptor structure
342 *
343 * This descriptor contains information about the device when running at
344 * the "other" speed (i.e. if the device is currently operating at high
345 * speed, this descriptor can be used to determine what would change if
346 * the device was operating at full speed.)
347 */
348typedef struct {
349 uint8_t bLength;
350 uint8_t bDescriptorType;
351 le16_t bcdUSB;
352 uint8_t bDeviceClass;
353 uint8_t bDeviceSubClass;
354 uint8_t bDeviceProtocol;
355 uint8_t bMaxPacketSize0;
356 uint8_t bNumConfigurations;
357 uint8_t bReserved;
358} usb_dev_qual_desc_t;
359
360/**
361 * \brief USB Device BOS descriptor structure
362 *
363 * The BOS descriptor (Binary device Object Store) defines a root
364 * descriptor that is similar to the configuration descriptor, and is
365 * the base descriptor for accessing a family of related descriptors.
366 * A host can read a BOS descriptor and learn from the wTotalLength field
367 * the entire size of the device-level descriptor set, or it can read in
368 * the entire BOS descriptor set of device capabilities.
369 * The host accesses this descriptor using the GetDescriptor() request.
370 * The descriptor type in the GetDescriptor() request is set to BOS.
371 */
372typedef struct {
373 uint8_t bLength;
374 uint8_t bDescriptorType;
375 le16_t wTotalLength;
376 uint8_t bNumDeviceCaps;
377} usb_dev_bos_desc_t;
378
379
380/**
381 * \brief USB Device Capabilities - USB 2.0 Extension Descriptor structure
382 *
383 * Defines the set of USB 1.1-specific device level capabilities.
384 */
385typedef struct {
386 uint8_t bLength;
387 uint8_t bDescriptorType;
388 uint8_t bDevCapabilityType;
389 le32_t bmAttributes;
390} usb_dev_capa_ext_desc_t;
391
392/**
393 * \brief USB Device LPM Descriptor structure
394 *
395 * The BOS descriptor and capabilities descriptors for LPM.
396 */
397typedef struct {
398 usb_dev_bos_desc_t bos;
399 usb_dev_capa_ext_desc_t capa_ext;
400} usb_dev_lpm_desc_t;
401
402/**
403 * \brief Standard USB Interface Association Descriptor structure
404 */
405typedef struct {
406 uint8_t bLength; //!< size of this descriptor in bytes
407 uint8_t bDescriptorType; //!< INTERFACE descriptor type
408 uint8_t bFirstInterface; //!< Number of interface
409 uint8_t bInterfaceCount; //!< value to select alternate setting
410 uint8_t bFunctionClass; //!< Class code assigned by the USB
411 uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB
412 uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB
413 uint8_t iFunction; //!< Index of string descriptor
414} usb_association_desc_t;
415
416
417/**
418 * \brief Standard USB configuration descriptor structure
419 */
420typedef struct {
421 uint8_t bLength;
422 uint8_t bDescriptorType;
423 le16_t wTotalLength;
424 uint8_t bNumInterfaces;
425 uint8_t bConfigurationValue;
426 uint8_t iConfiguration;
427 uint8_t bmAttributes;
428 uint8_t bMaxPower;
429} usb_conf_desc_t;
430
431
432#define USB_CONFIG_ATTR_MUST_SET (1 << 7) //!< Must always be set
433#define USB_CONFIG_ATTR_BUS_POWERED (0 << 6) //!< Bus-powered
434#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) //!< Self-powered
435#define USB_CONFIG_ATTR_REMOTE_WAKEUP (1 << 5) //!< remote wakeup supported
436
437#define USB_CONFIG_MAX_POWER(ma) (((ma) + 1) / 2) //!< Max power in mA
438
439/**
440 * \brief Standard USB association descriptor structure
441 */
442typedef struct {
443 uint8_t bLength; //!< Size of this descriptor in bytes
444 uint8_t bDescriptorType; //!< Interface descriptor type
445 uint8_t bFirstInterface; //!< Number of interface
446 uint8_t bInterfaceCount; //!< value to select alternate setting
447 uint8_t bFunctionClass; //!< Class code assigned by the USB
448 uint8_t bFunctionSubClass; //!< Sub-class code assigned by the USB
449 uint8_t bFunctionProtocol; //!< Protocol code assigned by the USB
450 uint8_t iFunction; //!< Index of string descriptor
451} usb_iad_desc_t;
452
453/**
454 * \brief Standard USB interface descriptor structure
455 */
456typedef struct {
457 uint8_t bLength;
458 uint8_t bDescriptorType;
459 uint8_t bInterfaceNumber;
460 uint8_t bAlternateSetting;
461 uint8_t bNumEndpoints;
462 uint8_t bInterfaceClass;
463 uint8_t bInterfaceSubClass;
464 uint8_t bInterfaceProtocol;
465 uint8_t iInterface;
466} usb_iface_desc_t;
467
468/**
469 * \brief Standard USB endpoint descriptor structure
470 */
471typedef struct {
472 uint8_t bLength;
473 uint8_t bDescriptorType;
474 uint8_t bEndpointAddress;
475 uint8_t bmAttributes;
476 le16_t wMaxPacketSize;
477 uint8_t bInterval;
478} usb_ep_desc_t;
479
480
481/**
482 * \brief A standard USB string descriptor structure
483 */
484typedef struct {
485 uint8_t bLength;
486 uint8_t bDescriptorType;
487} usb_str_desc_t;
488
489typedef struct {
490 usb_str_desc_t desc;
491 le16_t string[1];
492} usb_str_lgid_desc_t;
493
494COMPILER_PACK_RESET()
495
496//! @}
497
498#endif /* _USB_PROTOCOL_H_ */
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h b/tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h
new file mode 100644
index 000000000..479f25d4e
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h
@@ -0,0 +1,193 @@
1/**
2 * \file
3 *
4 * \brief USB Communication Device Class (CDC) protocol definitions
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46#ifndef _USB_PROTOCOL_CDC_H_
47#define _USB_PROTOCOL_CDC_H_
48
49#include "compiler.h"
50
51#ifdef CDC
52
53#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class
54#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface
55#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface
56
57#define CDC_SUBCLASS_DLCM 0x01 //!< Direct Line Control Model
58#define CDC_SUBCLASS_ACM 0x02 //!< Abstract Control Model
59#define CDC_SUBCLASS_TCM 0x03 //!< Telephone Control Model
60#define CDC_SUBCLASS_MCCM 0x04 //!< Multi-Channel Control Model
61#define CDC_SUBCLASS_CCM 0x05 //!< CAPI Control Model
62#define CDC_SUBCLASS_ETH 0x06 //!< Ethernet Networking Control Model
63#define CDC_SUBCLASS_ATM 0x07 //!< ATM Networking Control Model
64
65#define CDC_PROTOCOL_V25TER 0x01 //!< Common AT commands
66
67#define CDC_PROTOCOL_I430 0x30 //!< ISDN BRI
68#define CDC_PROTOCOL_HDLC 0x31 //!< HDLC
69#define CDC_PROTOCOL_TRANS 0x32 //!< Transparent
70#define CDC_PROTOCOL_Q921M 0x50 //!< Q.921 management protocol
71#define CDC_PROTOCOL_Q921 0x51 //!< Q.931 [sic] Data link protocol
72#define CDC_PROTOCOL_Q921TM 0x52 //!< Q.921 TEI-multiplexor
73#define CDC_PROTOCOL_V42BIS 0x90 //!< Data compression procedures
74#define CDC_PROTOCOL_Q931 0x91 //!< Euro-ISDN protocol control
75#define CDC_PROTOCOL_V120 0x92 //!< V.24 rate adaption to ISDN
76#define CDC_PROTOCOL_CAPI20 0x93 //!< CAPI Commands
77#define CDC_PROTOCOL_HOST 0xFD //!< Host based driver
78
79#define CDC_PROTOCOL_PUFD 0xFE
80
81#define CDC_CS_INTERFACE 0x24 //!< Interface Functional Descriptor
82#define CDC_CS_ENDPOINT 0x25 //!< Endpoint Functional Descriptor
83
84#define CDC_SCS_HEADER 0x00 //!< Header Functional Descriptor
85#define CDC_SCS_CALL_MGMT 0x01 //!< Call Management
86#define CDC_SCS_ACM 0x02 //!< Abstract Control Management
87#define CDC_SCS_UNION 0x06 //!< Union Functional Descriptor
88
89#define USB_REQ_CDC_SEND_ENCAPSULATED_COMMAND 0x00
90#define USB_REQ_CDC_GET_ENCAPSULATED_RESPONSE 0x01
91#define USB_REQ_CDC_SET_COMM_FEATURE 0x02
92#define USB_REQ_CDC_GET_COMM_FEATURE 0x03
93#define USB_REQ_CDC_CLEAR_COMM_FEATURE 0x04
94#define USB_REQ_CDC_SET_AUX_LINE_STATE 0x10
95#define USB_REQ_CDC_SET_HOOK_STATE 0x11
96#define USB_REQ_CDC_PULSE_SETUP 0x12
97#define USB_REQ_CDC_SEND_PULSE 0x13
98#define USB_REQ_CDC_SET_PULSE_TIME 0x14
99#define USB_REQ_CDC_RING_AUX_JACK 0x15
100#define USB_REQ_CDC_SET_LINE_CODING 0x20
101#define USB_REQ_CDC_GET_LINE_CODING 0x21
102#define USB_REQ_CDC_SET_CONTROL_LINE_STATE 0x22
103#define USB_REQ_CDC_SEND_BREAK 0x23
104#define USB_REQ_CDC_SET_RINGER_PARMS 0x30
105#define USB_REQ_CDC_GET_RINGER_PARMS 0x31
106#define USB_REQ_CDC_SET_OPERATION_PARMS 0x32
107#define USB_REQ_CDC_GET_OPERATION_PARMS 0x33
108#define USB_REQ_CDC_SET_LINE_PARMS 0x34
109#define USB_REQ_CDC_GET_LINE_PARMS 0x35
110#define USB_REQ_CDC_DIAL_DIGITS 0x36
111#define USB_REQ_CDC_SET_UNIT_PARAMETER 0x37
112#define USB_REQ_CDC_GET_UNIT_PARAMETER 0x38
113#define USB_REQ_CDC_CLEAR_UNIT_PARAMETER 0x39
114#define USB_REQ_CDC_GET_PROFILE 0x3A
115#define USB_REQ_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
116#define USB_REQ_CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x41
117#define USB_REQ_CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x42
118#define USB_REQ_CDC_SET_ETHERNET_PACKET_FILTER 0x43
119#define USB_REQ_CDC_GET_ETHERNET_STATISTIC 0x44
120#define USB_REQ_CDC_SET_ATM_DATA_FORMAT 0x50
121#define USB_REQ_CDC_GET_ATM_DEVICE_STATISTICS 0x51
122#define USB_REQ_CDC_SET_ATM_DEFAULT_VC 0x52
123#define USB_REQ_CDC_GET_ATM_VC_STATISTICS 0x53
124// Added bNotification codes according cdc spec 1.1 chapter 6.3
125#define USB_REQ_CDC_NOTIFY_RING_DETECT 0x09
126#define USB_REQ_CDC_NOTIFY_SERIAL_STATE 0x20
127#define USB_REQ_CDC_NOTIFY_CALL_STATE_CHANGE 0x28
128#define USB_REQ_CDC_NOTIFY_LINE_STATE_CHANGE 0x29
129
130
131#define CDC_CALL_MGMT_SUPPORTED (1 << 0)
132#define CDC_CALL_MGMT_OVER_DCI (1 << 1)
133#define CDC_ACM_SUPPORT_FEATURE_REQUESTS (1 << 0)
134#define CDC_ACM_SUPPORT_LINE_REQUESTS (1 << 1)
135#define CDC_ACM_SUPPORT_SENDBREAK_REQUESTS (1 << 2)
136#define CDC_ACM_SUPPORT_NOTIFY_REQUESTS (1 << 3)
137
138#pragma pack(push,1)
139typedef struct {
140 le32_t dwDTERate;
141 uint8_t bCharFormat;
142 uint8_t bParityType;
143 uint8_t bDataBits;
144} usb_cdc_line_coding_t;
145#pragma pack(pop)
146
147enum cdc_char_format {
148 CDC_STOP_BITS_1 = 0, //!< 1 stop bit
149 CDC_STOP_BITS_1_5 = 1, //!< 1.5 stop bits
150 CDC_STOP_BITS_2 = 2, //!< 2 stop bits
151};
152
153enum cdc_parity {
154 CDC_PAR_NONE = 0, //!< No parity
155 CDC_PAR_ODD = 1, //!< Odd parity
156 CDC_PAR_EVEN = 2, //!< Even parity
157 CDC_PAR_MARK = 3, //!< Parity forced to 0 (space)
158 CDC_PAR_SPACE = 4, //!< Parity forced to 1 (mark)
159};
160
161
162typedef struct {
163 uint16_t value;
164} usb_cdc_control_signal_t;
165
166#define CDC_CTRL_SIGNAL_ACTIVATE_CARRIER (1 << 1)
167#define CDC_CTRL_SIGNAL_DTE_PRESENT (1 << 0)
168
169
170typedef struct {
171 uint8_t bmRequestType;
172 uint8_t bNotification;
173 le16_t wValue;
174 le16_t wIndex;
175 le16_t wLength;
176} usb_cdc_notify_msg_t;
177
178typedef struct {
179 usb_cdc_notify_msg_t header;
180 le16_t value;
181} usb_cdc_notify_serial_state_t;
182
183#define CDC_SERIAL_STATE_DCD CPU_TO_LE16((1<<0))
184#define CDC_SERIAL_STATE_DSR CPU_TO_LE16((1<<1))
185#define CDC_SERIAL_STATE_BREAK CPU_TO_LE16((1<<2))
186#define CDC_SERIAL_STATE_RING CPU_TO_LE16((1<<3))
187#define CDC_SERIAL_STATE_FRAMING CPU_TO_LE16((1<<4))
188#define CDC_SERIAL_STATE_PARITY CPU_TO_LE16((1<<5))
189#define CDC_SERIAL_STATE_OVERRUN CPU_TO_LE16((1<<6))
190
191#endif
192
193#endif // _USB_PROTOCOL_CDC_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h b/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h
new file mode 100644
index 000000000..c482e9c06
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h
@@ -0,0 +1,319 @@
1/**
2 * \file
3 *
4 * \brief USB Human Interface Device (HID) protocol definitions.
5 *
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43/*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47#ifndef _USB_PROTOCOL_HID_H_
48#define _USB_PROTOCOL_HID_H_
49
50/**
51 * \ingroup usb_protocol_group
52 * \defgroup usb_hid_protocol USB Human Interface Device (HID)
53 * protocol definitions
54 * \brief USB Human Interface Device (HID) protocol definitions
55 *
56 * @{
57 */
58
59//! \name Possible Class value
60//@{
61#define HID_CLASS 0x03
62//@}
63
64//! \name Possible SubClass value
65//@{
66//! Interface subclass NO support BOOT protocol
67#define HID_SUB_CLASS_NOBOOT 0x00
68//! Interface subclass support BOOT protocol
69#define HID_SUB_CLASS_BOOT 0x01
70//@}
71
72//! \name Possible protocol value
73//@{
74//! Protocol generic standard
75#define HID_PROTOCOL_GENERIC 0x00
76//! Protocol keyboard standard
77#define HID_PROTOCOL_KEYBOARD 0x01
78//! Protocol mouse standard
79#define HID_PROTOCOL_MOUSE 0x02
80//@}
81
82
83//! \brief Hid USB requests (bRequest)
84enum usb_reqid_hid {
85 USB_REQ_HID_GET_REPORT = 0x01,
86 USB_REQ_HID_GET_IDLE = 0x02,
87 USB_REQ_HID_GET_PROTOCOL = 0x03,
88 USB_REQ_HID_SET_REPORT = 0x09,
89 USB_REQ_HID_SET_IDLE = 0x0A,
90 USB_REQ_HID_SET_PROTOCOL = 0x0B,
91};
92
93//! \brief HID USB descriptor types
94enum usb_descriptor_type_hid {
95 USB_DT_HID = 0x21,
96 USB_DT_HID_REPORT = 0x22,
97 USB_DT_HID_PHYSICAL = 0x23,
98};
99
100//! \brief HID Type for report descriptor
101enum usb_hid_item_report_type {
102 USB_HID_ITEM_REPORT_TYPE_MAIN = 0,
103 USB_HID_ITEM_REPORT_TYPE_GLOBAL = 1,
104 USB_HID_ITEM_REPORT_TYPE_LOCAL = 2,
105 USB_HID_ITEM_REPORT_TYPE_LONG = 3,
106};
107
108//! \brief HID report type
109enum usb_hid_report_type {
110 USB_HID_REPORT_TYPE_INPUT = 1,
111 USB_HID_REPORT_TYPE_OUTPUT = 2,
112 USB_HID_REPORT_TYPE_FEATURE = 3,
113};
114
115
116//! \brief HID protocol
117enum usb_hid_protocol {
118 USB_HID_PROCOTOL_BOOT = 0,
119 USB_HID_PROCOTOL_REPORT = 1,
120};
121
122COMPILER_PACK_SET(1)
123
124//! \brief HID Descriptor
125typedef struct {
126 uint8_t bLength; //!< Size of this descriptor in bytes
127 uint8_t bDescriptorType; //!< HID descriptor type
128 le16_t bcdHID; //!< Binary Coded Decimal Spec. release
129 uint8_t bCountryCode; //!< Hardware target country
130 uint8_t bNumDescriptors; //!< Number of HID class descriptors to follow
131 uint8_t bRDescriptorType; //!< Report descriptor type
132 le16_t wDescriptorLength; //!< Total length of Report descriptor
133} usb_hid_descriptor_t;
134
135COMPILER_PACK_RESET()
136
137 //! \name HID Report type
138 //! Used by SETUP_HID_GET_REPORT & SETUP_HID_SET_REPORT
139 //! @{
140#define REPORT_TYPE_INPUT 0x01
141#define REPORT_TYPE_OUTPUT 0x02
142#define REPORT_TYPE_FEATURE 0x03
143 //! @}
144
145 //! \name Constants of field DESCRIPTOR_HID
146 //! @{
147//! Numeric expression identifying the HID Class
148//! Specification release (here V1.11)
149#define USB_HID_BDC_V1_11 0x0111
150//! Numeric expression specifying the number of class descriptors
151//! Note: Always at least one i.e. Report descriptor.
152#define USB_HID_NUM_DESC 0x01
153
154 //! \name Country code
155 //! @{
156#define USB_HID_NO_COUNTRY_CODE 0 // Not Supported
157#define USB_HID_COUNTRY_ARABIC 1 // Arabic
158#define USB_HID_COUNTRY_BELGIAN 2 // Belgian
159#define USB_HID_COUNTRY_CANADIAN_BILINGUAL 3 // Canadian-Bilingual
160#define USB_HID_COUNTRY_CANADIAN_FRENCH 4 // Canadian-French
161#define USB_HID_COUNTRY_CZECH_REPUBLIC 5 // Czech Republic
162#define USB_HID_COUNTRY_DANISH 6 // Danish
163#define USB_HID_COUNTRY_FINNISH 7 // Finnish
164#define USB_HID_COUNTRY_FRENCH 8 // French
165#define USB_HID_COUNTRY_GERMAN 9 // German
166#define USB_HID_COUNTRY_GREEK 10 // Greek
167#define USB_HID_COUNTRY_HEBREW 11 // Hebrew
168#define USB_HID_COUNTRY_HUNGARY 12 // Hungary
169#define USB_HID_COUNTRY_INTERNATIONAL_ISO 13 // International (ISO)
170#define USB_HID_COUNTRY_ITALIAN 14 // Italian
171#define USB_HID_COUNTRY_JAPAN_KATAKANA 15 // Japan (Katakana)
172#define USB_HID_COUNTRY_KOREAN 16 // Korean
173#define USB_HID_COUNTRY_LATIN_AMERICAN 17 // Latin American
174#define USB_HID_COUNTRY_NETHERLANDS_DUTCH 18 // Netherlands/Dutch
175#define USB_HID_COUNTRY_NORWEGIAN 19 // Norwegian
176#define USB_HID_COUNTRY_PERSIAN_FARSI 20 // Persian (Farsi)
177#define USB_HID_COUNTRY_POLAND 21 // Poland
178#define USB_HID_COUNTRY_PORTUGUESE 22 // Portuguese
179#define USB_HID_COUNTRY_RUSSIA 23 // Russia
180#define USB_HID_COUNTRY_SLOVAKIA 24 // Slovakia
181#define USB_HID_COUNTRY_SPANISH 25 // Spanish
182#define USB_HID_COUNTRY_SWEDISH 26 // Swedish
183#define USB_HID_COUNTRY_SWISS_FRENCH 27 // Swiss/French
184#define USB_HID_COUNTRY_SWISS_GERMAN 28 // Swiss/German
185#define USB_HID_COUNTRY_SWITZERLAND 29 // Switzerland
186#define USB_HID_COUNTRY_TAIWAN 30 // Taiwan
187#define USB_HID_COUNTRY_TURKISH_Q 31 // Turkish-Q
188#define USB_HID_COUNTRY_UK 32 // UK
189#define USB_HID_COUNTRY_US 33 // US
190#define USB_HID_COUNTRY_YUGOSLAVIA 34 // Yugoslavia
191#define USB_HID_COUNTRY_TURKISH_F 35 // Turkish-F
192 //! @}
193 //! @}
194//! @}
195
196
197//! \name HID KEYS values
198//! @{
199#define HID_A 0x04
200#define HID_B 0x05
201#define HID_C 0x06
202#define HID_D 0x07
203#define HID_E 0x08
204#define HID_F 0x09
205#define HID_G 0x0A
206#define HID_H 0x0B
207#define HID_I 0x0C
208#define HID_J 0x0D
209#define HID_K 0x0E
210#define HID_L 0x0F
211#define HID_M 0x10
212#define HID_N 0x11
213#define HID_O 0x12
214#define HID_P 0x13
215#define HID_Q 0x14
216#define HID_R 0x15
217#define HID_S 0x16
218#define HID_T 0x17
219#define HID_U 0x18
220#define HID_V 0x19
221#define HID_W 0x1A
222#define HID_X 0x1B
223#define HID_Y 0x1C
224#define HID_Z 0x1D
225#define HID_1 30
226#define HID_2 31
227#define HID_3 32
228#define HID_4 33
229#define HID_5 34
230#define HID_6 35
231#define HID_7 36
232#define HID_8 37
233#define HID_9 38
234#define HID_0 39
235#define HID_ENTER 40
236#define HID_ESCAPE 41
237#define HID_BACKSPACE 42
238#define HID_TAB 43
239#define HID_SPACEBAR 44
240#define HID_UNDERSCORE 45
241#define HID_PLUS 46
242#define HID_OPEN_BRACKET 47 // {
243#define HID_CLOSE_BRACKET 48 // }
244#define HID_BACKSLASH 49
245#define HID_ASH 50 // # ~
246#define HID_COLON 51 // ; :
247#define HID_QUOTE 52 // ' "
248#define HID_TILDE 53
249#define HID_COMMA 54
250#define HID_DOT 55
251#define HID_SLASH 56
252#define HID_CAPS_LOCK 57
253#define HID_F1 58
254#define HID_F2 59
255#define HID_F3 60
256#define HID_F4 61
257#define HID_F5 62
258#define HID_F6 63
259#define HID_F7 64
260#define HID_F8 65
261#define HID_F9 66
262#define HID_F10 67
263#define HID_F11 68
264#define HID_F12 69
265#define HID_PRINTSCREEN 70
266#define HID_SCROLL_LOCK 71
267#define HID_PAUSE 72
268#define HID_INSERT 73
269#define HID_HOME 74
270#define HID_PAGEUP 75
271#define HID_DELETE 76
272#define HID_END 77
273#define HID_PAGEDOWN 78
274#define HID_RIGHT 79
275#define HID_LEFT 80
276#define HID_DOWN 81
277#define HID_UP 82
278#define HID_KEYPAD_NUM_LOCK 83
279#define HID_KEYPAD_DIVIDE 84
280#define HID_KEYPAD_AT 85
281#define HID_KEYPAD_MULTIPLY 85
282#define HID_KEYPAD_MINUS 86
283#define HID_KEYPAD_PLUS 87
284#define HID_KEYPAD_ENTER 88
285#define HID_KEYPAD_1 89
286#define HID_KEYPAD_2 90
287#define HID_KEYPAD_3 91
288#define HID_KEYPAD_4 92
289#define HID_KEYPAD_5 93
290#define HID_KEYPAD_6 94
291#define HID_KEYPAD_7 95
292#define HID_KEYPAD_8 96
293#define HID_KEYPAD_9 97
294#define HID_KEYPAD_0 98
295
296 //! \name HID modifier values
297 //! @{
298#define HID_MODIFIER_NONE 0x00
299#define HID_MODIFIER_LEFT_CTRL 0x01
300#define HID_MODIFIER_LEFT_SHIFT 0x02
301#define HID_MODIFIER_LEFT_ALT 0x04
302#define HID_MODIFIER_LEFT_UI 0x08
303#define HID_MODIFIER_RIGHT_CTRL 0x10
304#define HID_MODIFIER_RIGHT_SHIFT 0x20
305#define HID_MODIFIER_RIGHT_ALT 0x40
306#define HID_MODIFIER_RIGHT_UI 0x80
307 //! @}
308//! @}
309
310//! \name HID KEYS values
311//! @{
312#define HID_LED_NUM_LOCK (1<<0)
313#define HID_LED_CAPS_LOCK (1<<1)
314#define HID_LED_SCROLL_LOCK (1<<2)
315#define HID_LED_COMPOSE (1<<3)
316#define HID_LED_KANA (1<<4)
317//! @}
318
319#endif // _USB_PROTOCOL_HID_H_
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_util.c b/tmk_core/protocol/arm_atsam/usb/usb_util.c
new file mode 100644
index 000000000..58b349362
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_util.c
@@ -0,0 +1,59 @@
1#include "samd51j18a.h"
2#include "string.h"
3#include "usb_util.h"
4
5char digit(int d, int radix)
6{
7 if (d < 10)
8 {
9 return d + '0';
10 }
11 else
12 {
13 return d - 10 + 'A';
14 }
15}
16
17int UTIL_ltoa_radix(int64_t value, char *dest, int radix)
18{
19 int64_t original = value; //save original value
20 char buf[25] = "";
21 int c = sizeof(buf)-1;
22 int last = c;
23 int d;
24 int size;
25
26 if (value < 0) //if it's negative, take the absolute value
27 value = -value;
28
29 do //write least significant digit of value that's left
30 {
31 d = (value % radix);
32 buf[--c] = digit(d, radix);
33 value /= radix;
34 } while (value);
35
36 if (original < 0)
37 buf[--c] = '-';
38
39 size = last - c + 1; //includes null at end
40 memcpy(dest, &buf[c], last - c + 1);
41
42 return (size - 1); //without null termination
43}
44
45int UTIL_ltoa(int64_t value, char *dest)
46{
47 return UTIL_ltoa_radix(value, dest, 10);
48}
49
50int UTIL_itoa(int value, char *dest)
51{
52 return UTIL_ltoa_radix((int64_t)value, dest, 10);
53}
54
55int UTIL_utoa(uint32_t value, char *dest)
56{
57 return UTIL_ltoa_radix((int64_t)value, dest, 10);
58}
59
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_util.h b/tmk_core/protocol/arm_atsam/usb/usb_util.h
new file mode 100644
index 000000000..2134d5d27
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_util.h
@@ -0,0 +1,10 @@
1#ifndef _USB_UTIL_H_
2#define _USB_UTIL_H_
3
4int UTIL_ltoa_radix(int64_t value, char *dest, int radix);
5int UTIL_ltoa(int64_t value, char *dest);
6int UTIL_itoa(int value, char *dest);
7int UTIL_utoa(uint32_t value, char *dest);
8
9#endif //_USB_UTIL_H_
10
diff --git a/tmk_core/protocol/arm_atsam/wait_api.h b/tmk_core/protocol/arm_atsam/wait_api.h
new file mode 100644
index 000000000..424fbb53b
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/wait_api.h
@@ -0,0 +1,8 @@
1#ifndef _wait_api_h_
2#define _wait_api_h_
3
4void wait_ms(uint64_t msec);
5void wait_us(uint16_t usec);
6
7#endif
8