aboutsummaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
authorpatrickmt <40182064+patrickmt@users.noreply.github.com>2018-08-29 15:07:52 -0400
committerJack Humbert <jack.humb@gmail.com>2018-08-29 15:07:52 -0400
commit30680c6eb396a2bb06928afd69edae9908ac84fb (patch)
treea4a6c2598faa25dec208377a70dc0fb895ee9c8a /tmk_core
parenta6c770432f1348c44bc199029ce17b1b9ff4191c (diff)
downloadqmk_firmware-30680c6eb396a2bb06928afd69edae9908ac84fb.tar.gz
qmk_firmware-30680c6eb396a2bb06928afd69edae9908ac84fb.zip
Massdrop keyboard support (#3780)
* Massdrop SAMD51 Massdrop SAMD51 keyboards initial project upload * Removing relocated files Removing files that were relocated and not deleted from previous location * LED queue fix and cleaning Cleaned some white space or comments. Fix for LED I2C command queue. Cleaned up interrupts. Added debug function for printing numbers to scope through m15 line. * Factory programmed serial usage Ability to use factory programmed serial in hub and keyboard usb descriptors * USB serial number and bugfix Added support for factory programmed serial and usage. Incorporated bootloader's conditional compiling to align project closer. Fixed issue when USB device attempted to send before enabled. General white space and comment cleanup. * Project cleanup Cleaned up project in terms of white space, commented code, and unecessary files. NKRO keyboard is now using correct setreport although KBD was fine to use. Fixed broken linkage to __xprintf for serial debug statements. * Fix for extra keys Fixed possible USB hang on extra keys report set missing * I2C cleanup I2C cleanup and file renames necessary for master branch merge * Boot tracing and clocks cleanup Added optional boot debug trace mode through debug LED codes. General clock code cleanup. * Relocate ARM/Atmel headers Moved ARM/Atmel header folder from drivers to lib and made necessary makefile changes. * Pull request changes Pull request changes * Keymap and compile flag fix Keymap fix for momentary layer. Potential compile flag fix for Travis CI failure. * va_list include fix Fix for va_list compile failure * Include file case fixes Fixes for include files with incorrect case * ctrl and alt67 keyboard readme Added ctrl and alt67 keyboard readme files
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